Changeset cbcdd2c in sasview


Ignore:
Timestamp:
Mar 10, 2017 9:44:44 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:
cd31251
Parents:
5236449
Message:

QModel items conversion into SasModel? parameters + data display SASVIEW-535

Location:
src/sas
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/DataExplorer.py

    r5236449 rcbcdd2c  
    7373        self.contextMenu() 
    7474 
     75        # Same menus for the theory view 
     76        self.freezeView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) 
     77        self.freezeView.customContextMenuRequested.connect(self.onCustomContextMenu) 
     78 
    7579        # Connect the comboboxes 
    7680        self.cbSelect.currentIndexChanged.connect(self.selectData) 
    7781 
    7882        #self.closeEvent.connect(self.closeEvent) 
    79         # self.aboutToQuit.connect(self.closeEvent) 
     83        self.currentChanged.connect(self.onTabSwitch) 
    8084        self.communicator = self.parent.communicator() 
    8185        self.communicator.fileReadSignal.connect(self.loadFromURL) 
    8286        self.communicator.activeGraphsSignal.connect(self.updateGraphCombo) 
    8387        self.communicator.activeGraphName.connect(self.updatePlotName) 
    84         #self.communicator.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective) 
    8588        self.cbgraph.editTextChanged.connect(self.enableGraphCombo) 
    8689        self.cbgraph.currentIndexChanged.connect(self.enableGraphCombo) 
    8790 
    8891        self._perspective = self.parent.perspective() 
    89         self._perspective.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective) 
    9092 
    9193        # Proxy model for showing a subset of Data1D/Data2D content 
     
    111113        self.enableGraphCombo(None) 
    112114 
     115        # Current view on model 
     116        self.current_view = self.treeView 
     117 
    113118    def closeEvent(self, event): 
    114119        """ 
     
    116121        """ 
    117122        event.ignore() 
     123 
     124    def onTabSwitch(self, index): 
     125        """ Callback for tab switching signal """ 
     126        if index == 0: 
     127            self.current_view = self.treeView 
     128        else: 
     129            self.current_view = self.freezeView 
    118130 
    119131    def displayHelp(self): 
     
    725737        Show the right-click context menu in the data treeview 
    726738        """ 
    727         index = self.treeView.indexAt(position) 
     739        index = self.current_view.indexAt(position) 
     740        proxy = self.current_view.model() 
     741        model = proxy.sourceModel() 
     742 
    728743        if index.isValid(): 
    729             model_item = self.model.itemFromIndex(self.data_proxy.mapToSource(index)) 
     744            model_item = model.itemFromIndex(proxy.mapToSource(index)) 
    730745            # Find the mapped index 
    731746            orig_index = model_item.isCheckable() 
     
    736751                self.actionEditMask.setEnabled(is_2D) 
    737752                # Fire up the menu 
    738                 self.context_menu.exec_(self.treeView.mapToGlobal(position)) 
     753                self.context_menu.exec_(self.current_view.mapToGlobal(position)) 
    739754 
    740755    def showDataInfo(self): 
     
    742757        Show a simple read-only text edit with data information. 
    743758        """ 
    744         index = self.treeView.selectedIndexes()[0] 
    745         model_item = self.model.itemFromIndex(self.data_proxy.mapToSource(index)) 
     759        index = self.current_view.selectedIndexes()[0] 
     760        proxy = self.current_view.model() 
     761        model = proxy.sourceModel() 
     762        model_item = model.itemFromIndex(proxy.mapToSource(index)) 
     763 
    746764        data = GuiUtils.dataFromItem(model_item) 
    747765        if isinstance(data, Data1D): 
     
    769787        Save the data points as either txt or xml 
    770788        """ 
    771         index = self.treeView.selectedIndexes()[0] 
    772         model_item = self.model.itemFromIndex(self.data_proxy.mapToSource(index)) 
     789        index = self.current_view.selectedIndexes()[0] 
     790        proxy = self.current_view.model() 
     791        model = proxy.sourceModel() 
     792        model_item = model.itemFromIndex(proxy.mapToSource(index)) 
     793 
    773794        data = GuiUtils.dataFromItem(model_item) 
    774795        if isinstance(data, Data1D): 
     
    781802        Frozen plot - display an image of the plot 
    782803        """ 
    783         index = self.treeView.selectedIndexes()[0] 
    784         model_item = self.model.itemFromIndex(self.data_proxy.mapToSource(index)) 
     804        index = self.current_view.selectedIndexes()[0] 
     805        proxy = self.current_view.model() 
     806        model = proxy.sourceModel() 
     807        model_item = model.itemFromIndex(proxy.mapToSource(index)) 
     808 
    785809        data = GuiUtils.dataFromItem(model_item) 
    786810 
     
    805829        Slowish 3D plot 
    806830        """ 
    807         index = self.treeView.selectedIndexes()[0] 
    808         model_item = self.model.itemFromIndex(self.data_proxy.mapToSource(index)) 
     831        index = self.current_view.selectedIndexes()[0] 
     832        proxy = self.current_view.model() 
     833        model = proxy.sourceModel() 
     834        model_item = model.itemFromIndex(proxy.mapToSource(index)) 
     835 
    809836        data = GuiUtils.dataFromItem(model_item) 
    810837 
     
    824851        Mask Editor for 2D plots 
    825852        """ 
    826         index = self.treeView.selectedIndexes()[0] 
    827         model_item = self.model.itemFromIndex(self.data_proxy.mapToSource(index)) 
     853        index = self.current_view.selectedIndexes()[0] 
     854        proxy = self.current_view.model() 
     855        model = proxy.sourceModel() 
     856        model_item = model.itemFromIndex(proxy.mapToSource(index)) 
     857 
    828858        data = GuiUtils.dataFromItem(model_item) 
    829859 
  • src/sas/qtgui/GuiManager.py

    r5236449 rcbcdd2c  
    182182            self._current_perspective.close() 
    183183        # Default perspective 
    184         self._current_perspective = Perspectives.PERSPECTIVES[str(perspective_name)](self) 
     184        self._current_perspective = Perspectives.PERSPECTIVES[str(perspective_name)](manager=self, parent=self) 
    185185        self._workspace.workspace.addWindow(self._current_perspective) 
    186186        self._current_perspective.show() 
     
    335335        self.communicate.progressBarUpdateSignal.connect(self.updateProgressBar) 
    336336        self.communicate.perspectiveChangedSignal.connect(self.perspectiveChanged) 
     337        self.communicate.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective) 
    337338 
    338339    def addTriggers(self): 
     
    721722        self.checkUpdate() 
    722723 
    723         pass 
    724  
     724    def updateTheoryFromPerspective(self, index): 
     725        """ 
     726        Catch the theory update signal from a perspective 
     727        Send the request to the DataExplorer for updating the theory model. 
     728        """ 
     729        self.filesWidget.updateTheoryFromPerspective(index) 
     730 
     731 
     732 
  • src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py

    r5236449 rcbcdd2c  
    1212    """ 
    1313    """ 
    14     updateTheoryFromPerspectiveSignal =  QtCore.pyqtSignal(QtGui.QStandardItem) 
    1514    name = "Fitting" # For displaying in the combo box in DataExplorer 
    1615    def __init__(self, manager=None, parent=None, data=None): 
     
    4443        self.setWindowTitle('Fit panel - Active Fitting Optimizer: %s' % self.optimizer) 
    4544 
    46         self.communicate = GuiUtils.Communicate() 
     45        #self.communicate = GuiUtils.Communicate() 
     46        self.communicate = self.parent.communicator() 
    4747 
    4848    def addFit(self, data): 
     
    5454        self.maxIndex += 1 
    5555        self.addTab(tab, self.tabName()) 
    56         tab.signalTheory.connect(self.passSignal) 
    5756 
    5857    def tabName(self): 
     
    6766        Update local bookkeeping on tab close 
    6867        """ 
    69         assert(len(self.tabs) >= index) 
     68        assert len(self.tabs) >= index 
    7069        # don't remove the last tab 
    7170        if len(self.tabs) <= 1: 
     
    8685        Pass it over to the calculator 
    8786        """ 
    88         assert(data_item is not None) 
     87        assert data_item is not None 
    8988 
    9089        if not isinstance(data_item, list): 
     
    9897        self._model_item = data_item[0] 
    9998 
    100         # Extract data on 1st child - this is the Data1D/2D component 
    101         data = GuiUtils.dataFromItem(self._model_item) 
    102  
    103         # self.model.item(WIDGETS.W_FILENAME).setData(QtCore.QVariant(self._model_item.text())) 
    104  
    10599        # Find the first unassigned tab. 
    106100        # If none, open a new tab. 
    107         available_tabs = list(map(lambda tab:tab.acceptsData(), self.tabs)) 
     101        available_tabs = list(map(lambda tab: tab.acceptsData(), self.tabs)) 
    108102 
    109103        if numpy.any(available_tabs): 
     
    111105        else: 
    112106            self.addFit(data_item) 
    113  
    114  
    115     def passSignal(self, theory_item): 
    116         """ 
    117         """ 
    118         self.updateTheoryFromPerspectiveSignal.emit(theory_item) 
    119  
    120 if __name__ == "__main__": 
    121     app = QtGui.QApplication([]) 
    122     dlg = FittingWindow() 
    123     dlg.show() 
    124     sys.exit(app.exec_()) 
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    r5236449 rcbcdd2c  
    77import logging 
    88import traceback 
    9  
     9from twisted.internet import threads 
    1010 
    1111from PyQt4 import QtGui 
     
    2323from sas.sascalc.dataloader.data_info import Source 
    2424from sas.sasgui.perspectives.fitting.model_thread import Calc1D 
     25from sas.sasgui.perspectives.fitting.model_thread import Calc2D 
    2526 
    2627from UI.FittingWidgetUI import Ui_FittingWidgetUI 
     
    2829TAB_MAGNETISM = 4 
    2930TAB_POLY = 3 
    30 CATEGORY_DEFAULT="Choose category..." 
     31CATEGORY_DEFAULT = "Choose category..." 
     32QMIN_DEFAULT = 0.0005 
     33QMAX_DEFAULT = 0.5 
     34NPTS_DEFAULT = 50 
    3135 
    3236class FittingWidget(QtGui.QWidget, Ui_FittingWidgetUI): 
     
    3438    Main widget for selecting form and structure factor models 
    3539    """ 
    36     signalTheory =  QtCore.pyqtSignal(QtGui.QStandardItem) 
    37  
    3840    def __init__(self, manager=None, parent=None, data=None, id=1): 
    3941        """ 
     
    4648 
    4749        # Necessary globals 
     50        self.parent = parent 
     51        # SasModel is loaded 
    4852        self.model_is_loaded = False 
     53        # Data[12]D passed and set 
    4954        self.data_is_loaded = False 
     55        # Current SasModel in view 
    5056        self.kernel_module = None 
     57        # Current SasModel view dimension 
    5158        self.is2D = False 
     59        # Current SasModel is multishell 
    5260        self.model_has_shells = False 
     61        # Utility variable to enable unselectable option in category combobox 
    5362        self._previous_category_index = 0 
     63        # Utility variable for multishell display 
    5464        self._last_model_row = 0 
    55         self._current_parameter_name = None 
     65        # Dictionary of {model name: model class} for the current category 
    5666        self.models = {} 
    5767 
     
    6070 
    6171        # Parameters 
    62         self.q_range_min = 0.0005 
    63         self.q_range_max = 0.5 
    64         self.npts = 20 
     72        self.q_range_min = QMIN_DEFAULT 
     73        self.q_range_max = QMAX_DEFAULT 
     74        self.npts = NPTS_DEFAULT 
     75        # Main Data[12]D holder 
    6576        self._data = None 
    6677 
     
    6879        self.setupUi(self) 
    6980        self.setWindowTitle("Fitting") 
    70         self.communicate = GuiUtils.Communicate() 
     81        self.communicate = self.parent.communicate 
    7182 
    7283        # Set the main models 
     
    7485        self._poly_model = QtGui.QStandardItemModel() 
    7586        self._magnet_model = QtGui.QStandardItemModel() 
    76         # Proxy model for custom views on the main _model_model 
    77         self.proxyModel = QtGui.QSortFilterProxyModel() 
    7887 
    7988        # Param model displayed in param list 
     
    124133    def data(self, value): 
    125134        """ data setter """ 
     135        # _index contains the QIndex with data 
    126136        self._index = value 
     137        # _data contains the actual Data[12]D 
    127138        self._data = GuiUtils.dataFromItem(value[0]) 
    128139        self.data_is_loaded = True 
     140        # Tag along functionality 
    129141        self.updateQRange() 
    130142        self.cmdFit.setEnabled(True) 
     
    135147 
    136148    def disableModelCombo(self): 
     149        """ Disable the combobox """ 
    137150        self.cbModel.setEnabled(False) 
    138151        self.label_3.setEnabled(False) 
    139152 
    140153    def enableModelCombo(self): 
     154        """ Enable the combobox """ 
    141155        self.cbModel.setEnabled(True) 
    142156        self.label_3.setEnabled(True) 
    143157 
    144158    def disableStructureCombo(self): 
     159        """ Disable the combobox """ 
    145160        self.cbStructureFactor.setEnabled(False) 
    146161        self.label_4.setEnabled(False) 
    147162 
    148163    def enableStructureCombo(self): 
     164        """ Enable the combobox """ 
    149165        self.cbStructureFactor.setEnabled(True) 
    150166        self.label_4.setEnabled(True) 
     
    156172        if self.data_is_loaded: 
    157173            self.q_range_min, self.q_range_max, self.npts = self.computeDataRange(self.data) 
    158         # set Q range labels 
     174        # set Q range labels on the main tab 
    159175        self.lblMinRangeDef.setText(str(self.q_range_min)) 
    160176        self.lblMaxRangeDef.setText(str(self.q_range_max)) 
    161  
     177        # set Q range labels on the options tab 
    162178        self.txtMaxRange.setText(str(self.q_range_max)) 
    163179        self.txtMinRange.setText(str(self.q_range_min)) 
     
    176192        self.chkMagnetism.setEnabled(False) 
    177193        self.chkMagnetism.setCheckState(False) 
    178         # tabs 
     194        # Tabs 
    179195        self.tabFitting.setTabEnabled(TAB_POLY, False) 
    180196        self.tabFitting.setTabEnabled(TAB_MAGNETISM, False) 
    181197        self.lblChi2Value.setText("---") 
    182      
    183198        # Update Q Ranges 
    184199        self.updateQRange() 
     
    188203        Connect GUI element signals 
    189204        """ 
     205        # Comboboxes 
    190206        self.cbStructureFactor.currentIndexChanged.connect(self.selectStructureFactor) 
    191207        self.cbCategory.currentIndexChanged.connect(self.selectCategory) 
    192208        self.cbModel.currentIndexChanged.connect(self.selectModel) 
     209        # Checkboxes 
    193210        self.chk2DView.toggled.connect(self.toggle2D) 
    194211        self.chkPolydispersity.toggled.connect(self.togglePoly) 
    195212        self.chkMagnetism.toggled.connect(self.toggleMagnetism) 
     213        # Buttons 
    196214        self.cmdFit.clicked.connect(self.onFit) 
     215        self.cmdPlot.clicked.connect(self.onPlot) 
     216        # Line edits 
     217        self.txtNpts.textChanged.connect(self.onNpts) 
     218        self.txtMinRange.textChanged.connect(self.onMinRange) 
     219        self.txtMaxRange.textChanged.connect(self.onMaxRange) 
     220 
     221        # Respond to change in parameters from the UI 
     222        self._model_model.itemChanged.connect(self.updateParamsFromModel) 
    197223 
    198224    def setDefaultStructureCombo(self): 
    199         # Fill in the structure factors combo box with defaults 
     225        """ 
     226        Fill in the structure factors combo box with defaults 
     227        """ 
    200228        structure_factor_list = self.master_category_dict.pop('Structure Factor') 
    201229        structure_factors = [] 
     
    208236        """ 
    209237        Select Category from list 
    210         :return: 
    211238        """ 
    212239        category = self.cbCategory.currentText() 
     
    224251            return 
    225252 
     253        # Safely clear and enable the model combo 
    226254        self.cbModel.blockSignals(True) 
    227255        self.cbModel.clear() 
     
    231259 
    232260        self._previous_category_index = self.cbCategory.currentIndex() 
     261        # Retrieve the list of models 
    233262        model_list = self.master_category_dict[str(category)] 
    234263        models = [] 
     264        # Populate the models combobox 
    235265        for (model, _) in model_list: 
    236266            models.append(model) 
     
    241271        Respond to select Model from list event 
    242272        """ 
    243         model = self.cbModel.currentText() 
    244         self._current_parameter_name = model 
     273        model = str(self.cbModel.currentText()) 
    245274 
    246275        # SasModel -> QModel 
     
    248277 
    249278        if self._index is None: 
     279            # Create default datasets if no data passed 
    250280            if self.is2D: 
    251281                self.createDefault2dData() 
    252282            else: 
    253283                self.createDefault1dData() 
    254             self.createTheoryIndex() 
     284            # DESIGN: create the theory now or on Plot event? 
     285            #self.createTheoryIndex() 
    255286        else: 
    256             # TODO: 2D case 
     287            # Create datasets and errorbars for current data 
     288            if self.is2D: 
     289                self.calculate2DForModel() 
     290            else: 
     291                self.calculate1DForModel() 
    257292            # TODO: attach the chart to index 
    258             self.calculate1DForModel() 
    259293 
    260294    def selectStructureFactor(self): 
    261295        """ 
    262296        Select Structure Factor from list 
    263         :param: 
    264         :return: 
    265         """ 
    266         model = self.cbStructureFactor.currentText() 
     297        """ 
     298        model = str(self.cbStructureFactor.currentText()) 
    267299        self.setModelModel(model) 
    268300 
     
    275307        self.model_enabled_dict = defaultdict(bool) 
    276308 
    277         try: 
    278             categorization_file = CategoryInstaller.get_user_file() 
    279             if not os.path.isfile(categorization_file): 
    280                 categorization_file = CategoryInstaller.get_default_file() 
    281             cat_file = open(categorization_file, 'rb') 
     309        categorization_file = CategoryInstaller.get_user_file() 
     310        if not os.path.isfile(categorization_file): 
     311            categorization_file = CategoryInstaller.get_default_file() 
     312        with open(categorization_file, 'rb') as cat_file: 
    282313            self.master_category_dict = json.load(cat_file) 
    283314            self.regenerateModelDict() 
    284             cat_file.close() 
    285         except IOError: 
    286             raise 
    287             print 'Problem reading in category file.' 
    288             print 'We even looked for it, made sure it was there.' 
    289             print 'An existential crisis if there ever was one.' 
    290315 
    291316        # Load the model dict 
     
    296321    def regenerateModelDict(self): 
    297322        """ 
    298         regenerates self.by_model_dict which has each model name as the 
     323        Regenerates self.by_model_dict which has each model name as the 
    299324        key and the list of categories belonging to that model 
    300325        along with the enabled mapping 
     
    310335        Returns a list of all multi-shell parameters in 'model' 
    311336        """ 
    312         iter_params = list(filter(lambda par: "[" in par.name, model.iq_parameters)) 
    313  
    314         return iter_params 
     337        return list(filter(lambda par: "[" in par.name, model.iq_parameters)) 
    315338 
    316339    def getMultiplicity(self, model): 
     
    333356        Adds background parameter with default values to the model 
    334357        """ 
    335         assert(isinstance(model, QtGui.QStandardItemModel)) 
    336  
     358        assert isinstance(model, QtGui.QStandardItemModel) 
    337359        checked_list = ['background', '0.001', '-inf', 'inf', '1/cm'] 
    338360        self.addCheckedListToModel(model, checked_list) 
     
    342364        Adds scale parameter with default values to the model 
    343365        """ 
    344         assert(isinstance(model, QtGui.QStandardItemModel)) 
    345  
     366        assert isinstance(model, QtGui.QStandardItemModel) 
    346367        checked_list = ['scale', '1.0', '0.0', 'inf', ''] 
    347368        self.addCheckedListToModel(model, checked_list) 
    348369 
    349370    def addCheckedListToModel(self, model, param_list): 
    350         assert(isinstance(model, QtGui.QStandardItemModel)) 
     371        assert isinstance(model, QtGui.QStandardItemModel) 
    351372        item_list = [QtGui.QStandardItem(item) for item in param_list] 
    352373        item_list[0].setCheckable(True) 
     
    377398    def setModelModel(self, model_name): 
    378399        """ 
    379         Setting model parameters into table based on selected 
    380         :param model_name: 
    381         """ 
     400        Setting model parameters into table based on selected category 
     401        """ 
     402        assert isinstance(model_name, str) 
     403 
    382404        # Crete/overwrite model items 
    383405        self._model_model.clear() 
    384         model_name = str(model_name) 
    385406 
    386407        kernel_module = generate.load_kernel_module(model_name) 
    387         #model_info = modelinfo.make_model_info(kernel_module) 
    388         #self.kernel_module = _make_model_from_info(model_info) 
    389408        self.model_parameters = modelinfo.make_parameter_table(getattr(kernel_module, 'parameters', [])) 
    390409 
    391         # Instantiate the current model 
     410        # Instantiate the current sasmodel 
    392411        self.kernel_module = self.models[model_name]() 
    393412 
     
    413432        self.updateQRange() 
    414433 
     434    def updateParamsFromModel(self, item): 
     435        """ 
     436        Callback method for updating the sasmodel parameters with the GUI values 
     437        """ 
     438        # Extract changed value. Assumes proper validation by QValidator/Delegate 
     439        value = float(item.text()) 
     440        model_column = item.column() 
     441        model_row = item.row() 
     442        name_index = self._model_model.index(model_row, 0) 
     443        parameter_name = str(self._model_model.data(name_index).toPyObject()) # sld, background etc. 
     444        property_name = str(self._model_model.headerData(1, model_column).toPyObject()) # Value, min, max, etc. 
     445 
     446        print "%s(%s) => %d" % (parameter_name, property_name, value) 
     447        self.kernel_module.params[parameter_name] = value 
     448 
     449        # min/max to be changed in self.kernel_module.details[parameter_name] = ['Ang', 0.0, inf] 
     450 
     451        # magnetic params in self.kernel_module.details['M0:parameter_name'] = value 
     452        # multishell params in self.kernel_module.details[??] = value 
     453 
    415454    def computeDataRange(self, data): 
    416455        """ 
    417         compute the minimum and the maximum range of the data 
     456        Compute the minimum and the maximum range of the data 
    418457        return the npts contains in data 
    419458        """ 
    420         assert(data is not None) 
    421         assert((isinstance(data, Data1D) or isinstance(data, Data2D))) 
     459        assert data is not None 
     460        assert (isinstance(data, Data1D) or isinstance(data, Data2D)) 
    422461        qmin, qmax, npts = None, None, None 
    423462        if isinstance(data, Data1D): 
     
    426465                qmax = max(data.x) 
    427466                npts = len(data.x) 
    428             except: 
     467            except (ValueError, TypeError): 
    429468                msg = "Unable to find min/max/length of \n data named %s" % \ 
    430469                            data.filename 
     
    436475                x = max(numpy.fabs(data.xmin), numpy.fabs(data.xmax)) 
    437476                y = max(numpy.fabs(data.ymin), numpy.fabs(data.ymax)) 
    438             except: 
     477            except (ValueError, TypeError): 
    439478                msg = "Unable to find min/max of \n data named %s" % \ 
    440479                            data.filename 
    441480                raise ValueError, msg 
    442             qmax = math.sqrt(x * x + y * y) 
     481            qmax = numpy.sqrt(x * x + y * y) 
    443482            npts = len(data.data) 
    444483        return qmin, qmax, npts 
     
    470509                # Find param in volume_params 
    471510                for p in parameters.form_volume_parameters: 
    472                     if p.name == param.name: 
    473                         item1_2 = QtGui.QStandardItem(str(p.default)) 
    474                         item1_3 = QtGui.QStandardItem(str(p.limits[0])) 
    475                         item1_4 = QtGui.QStandardItem(str(p.limits[1])) 
    476                         item1_5 = QtGui.QStandardItem(p.units) 
    477                         poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 
    478                         break 
    479  
     511                    if p.name != param.name: 
     512                        continue 
     513                    item1_2 = QtGui.QStandardItem(str(p.default)) 
     514                    item1_3 = QtGui.QStandardItem(str(p.limits[0])) 
     515                    item1_4 = QtGui.QStandardItem(str(p.limits[1])) 
     516                    item1_5 = QtGui.QStandardItem(p.units) 
     517                    poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 
     518                    break 
     519                # Add the polydisp item as a child 
    480520                item1.appendRow([poly_item]) 
    481  
     521            # Param values 
    482522            item2 = QtGui.QStandardItem(str(param.default)) 
     523            # TODO: the error column. 
     524            # Either add a proxy model or a custom view delegate 
     525            #item_err = QtGui.QStandardItem() 
    483526            item3 = QtGui.QStandardItem(str(param.limits[0])) 
    484527            item4 = QtGui.QStandardItem(str(param.limits[1])) 
     
    486529            model.appendRow([item1, item2, item3, item4, item5]) 
    487530 
     531        # Update the counter used for multishell display 
    488532        self._last_model_row = self._model_model.rowCount() 
    489533 
     
    571615        Create a QStandardModelIndex containing default model data 
    572616        """ 
    573         name = self._current_parameter_name 
     617        name = self.kernel_module.name 
    574618        if self.is2D: 
    575619            name += "2d" 
    576620        name = "M%i [%s]" % (self.tab_id, name) 
    577621        new_item = GuiUtils.createModelItemWithPlot(QtCore.QVariant(self.data), name=name) 
    578         self.signalTheory.emit(new_item) 
     622        # Notify the GUI manager so it can update the theory model in DataExplorer 
     623        self.communicate.updateTheoryFromPerspectiveSignal.emit(new_item) 
    579624 
    580625    def onFit(self): 
     
    582627        Perform fitting on the current data 
    583628        """ 
    584         # TEST FOR DISPLAY. 
    585         self.calculate1DForModel() 
     629        #self.calculate1DForModel() 
     630        pass 
     631 
     632    def onPlot(self): 
     633        """ 
     634        Plot the current set of data 
     635        """ 
     636        # TODO: reimplement basepage.py/_update_paramv_on_fit 
     637        if self.data is None or not self._data.is_data: 
     638            self.createDefault2dData() if self.is2D else self.createDefault1dData() 
     639        self.calculate2DForModel() if self.is2D else self.calculate1DForModel() 
     640 
     641    def onNpts(self, text): 
     642        """ 
     643        Callback for number of points line edit update 
     644        """ 
     645        # assumes type/value correctness achieved with QValidator 
     646        try: 
     647            self.npts = int(text) 
     648        except: 
     649            pass 
     650 
     651    def onMinRange(self, text): 
     652        """ 
     653        Callback for minimum range of points line edit update 
     654        """ 
     655        # assumes type/value correctness achieved with QValidator 
     656        try: 
     657            self.q_range_min = float(text) 
     658            # set Q range labels on the main tab 
     659            self.lblMinRangeDef.setText(str(self.q_range_min)) 
     660        except: 
     661            pass 
     662 
     663    def onMaxRange(self, text): 
     664        """ 
     665        Callback for maximum range of points line edit update 
     666        """ 
     667        # assumes type/value correctness achieved with QValidator 
     668        try: 
     669            self.q_range_max = float(text) 
     670            # set Q range labels on the main tab 
     671            self.lblMaxRangeDef.setText(str(self.q_range_max)) 
     672        except: 
     673            pass 
    586674 
    587675    def calculate1DForModel(self): 
     
    589677        Prepare the fitting data object, based on current ModelModel 
    590678        """ 
    591         data = self.data 
    592         model = self.kernel_module 
    593         page_id = 0 
    594         qmin = self.q_range_min 
    595         qmax = self.q_range_max 
    596         smearer = None 
    597         state = None 
    598         weight = None 
    599         fid = None 
    600         toggle_mode_on = False 
    601         update_chisqr = False 
    602         source = None 
    603  
    604         self.calc_1D = Calc1D(data=data, 
    605                               model=model, 
    606                               page_id=page_id, 
    607                               qmin=qmin, 
    608                               qmax=qmax, 
    609                               smearer=smearer, 
    610                               state=state, 
    611                               weight=weight, 
    612                               fid=fid, 
    613                               toggle_mode_on=toggle_mode_on, 
     679        self.calc_1D = Calc1D(data=self.data, 
     680                              model=self.kernel_module, 
     681                              page_id=0, 
     682                              qmin=self.q_range_min, 
     683                              qmax=self.q_range_max, 
     684                              smearer=None, 
     685                              state=None, 
     686                              weight=None, 
     687                              fid=None, 
     688                              toggle_mode_on=False, 
    614689                              completefn=self.complete1D, 
    615                               update_chisqr=update_chisqr, 
     690                              update_chisqr=True, 
    616691                              exception_handler=self.calcException, 
    617                               source=source) 
    618         self.calc_1D.queue() 
    619  
    620     def complete1D(self, x, y, page_id, elapsed, index, model, 
    621                    weight=None, fid=None, 
    622                    toggle_mode_on=False, state=None, 
    623                    data=None, update_chisqr=True, 
    624                    source='model', plot_result=True): 
     692                              source=None) 
     693        # Instead of starting the thread with 
     694        #   self.calc_1D.queue() 
     695        # let's try running the async request 
     696        calc_thread = threads.deferToThread(self.calc_1D.compute) 
     697        calc_thread.addCallback(self.complete1D) 
     698 
     699    def complete1D(self, return_data): 
    625700        """ 
    626701        Plot the current data 
    627         Should be a rewrite of fitting.py/_complete1D 
    628         """ 
    629         print "THREAD FINISHED" 
     702        """ 
     703        # Unpack return data from Calc1D 
     704        x, y, page_id, state, weight,\ 
     705        fid, toggle_mode_on, \ 
     706        elapsed, index, model,\ 
     707        data, update_chisqr, source = return_data 
     708 
     709        # Create the new plot 
     710        new_plot = Data1D(x=x, y=y) 
     711        new_plot.is_data = False 
     712        new_plot.dy = numpy.zeros(len(y)) 
     713        _yaxis, _yunit = data.get_yaxis() 
     714        _xaxis, _xunit = data.get_xaxis() 
     715        new_plot.title = data.name 
     716 
     717        new_plot.group_id = data.group_id 
     718        if new_plot.group_id == None: 
     719            new_plot.group_id = data.group_id 
     720        new_plot.id = str(self.tab_id) + " " + data.name 
     721        new_plot.name = model.name + " [" + data.name + "]" 
     722        new_plot.xaxis(_xaxis, _xunit) 
     723        new_plot.yaxis(_yaxis, _yunit) 
     724 
     725        # Assign the new Data1D object-wide 
     726        self._data = new_plot 
     727        self.createTheoryIndex() 
     728 
     729        #output=self._cal_chisqr(data=data, 
     730        #                        fid=fid, 
     731        #                        weight=weight, 
     732        #                        page_id=page_id, 
     733        #                        index=index) 
     734 
     735    def calculate2DForModel(self): 
     736        """ 
     737        Prepare the fitting data object, based on current ModelModel 
     738        """ 
     739        self.calc_2D = Calc2D(data=self.data, 
     740                              model=self.kernel_module, 
     741                              page_id=0, 
     742                              qmin=self.q_range_min, 
     743                              qmax=self.q_range_max, 
     744                              smearer=None, 
     745                              state=None, 
     746                              weight=None, 
     747                              fid=None, 
     748                              toggle_mode_on=False, 
     749                              completefn=self.complete2D, 
     750                              update_chisqr=True, 
     751                              exception_handler=self.calcException, 
     752                              source=None) 
     753 
     754        # Instead of starting the thread with 
     755        #    self.calc_2D.queue() 
     756        # let's try running the async request 
     757        calc_thread = threads.deferToThread(self.calc_2D.compute) 
     758        calc_thread.addCallback(self.complete2D) 
     759 
     760    def complete2D(self, return_data): 
     761        """ 
     762        Plot the current data 
     763        Should be a rewrite of fitting.py/_complete2D 
     764        """ 
     765        image, data, page_id, model, state, toggle_mode_on,\ 
     766        elapsed, index, fid, qmin, qmax, weight, \ 
     767        update_chisqr, source = return_data 
     768 
     769        numpy.nan_to_num(image) 
     770        new_plot = Data2D(image=image, err_image=data.err_data) 
     771        new_plot.name = model.name + '2d' 
     772        new_plot.title = "Analytical model 2D " 
     773        new_plot.id = str(page_id) + " " + data.name 
     774        new_plot.group_id = str(page_id) + " Model2D" 
     775        new_plot.detector = data.detector 
     776        new_plot.source = data.source 
     777        new_plot.is_data = False 
     778        new_plot.qx_data = data.qx_data 
     779        new_plot.qy_data = data.qy_data 
     780        new_plot.q_data = data.q_data 
     781        new_plot.mask = data.mask 
     782        ## plot boundaries 
     783        new_plot.ymin = data.ymin 
     784        new_plot.ymax = data.ymax 
     785        new_plot.xmin = data.xmin 
     786        new_plot.xmax = data.xmax 
     787 
     788        title = data.title 
     789 
     790        new_plot.is_data = False 
     791        if data.is_data: 
     792            data_name = str(data.name) 
     793        else: 
     794            data_name = str(model.__class__.__name__) + '2d' 
     795 
     796        if len(title) > 1: 
     797            new_plot.title = "Model2D for %s " % model.name + data_name 
     798        new_plot.name = model.name + " [" + \ 
     799                                    data_name + "]" 
     800 
     801        # Assign the new Data2D object-wide 
     802        self._data = new_plot 
     803        self.createTheoryIndex() 
     804 
     805        #output=self._cal_chisqr(data=data, 
     806        #                        weight=weight, 
     807        #                        fid=fid, 
     808        #                        page_id=page_id, 
     809        #                        index=index) 
     810        #    self._plot_residuals(page_id=page_id, data=data, fid=fid, 
     811        #                            index=index, weight=weight) 
    630812 
    631813    def calcException(self, etype, value, tb): 
    632814        """ 
    633         """ 
    634         print "THREAD EXCEPTION" 
     815        Something horrible happened in the deferred. Cry me a river. 
     816        """ 
    635817        logging.error("".join(traceback.format_exception(etype, value, tb))) 
    636818        msg = traceback.format_exception(etype, value, tb, limit=1) 
     
    640822        Updates parameter name from <param_name>[n_shell] to <param_name>value 
    641823        """ 
    642         assert('[' in param_name) 
     824        assert '[' in param_name 
    643825        return param_name[:param_name.index('[')]+str(value) 
    644826 
     
    646828        """ 
    647829        Setting table properties 
    648         :param table: 
    649         :return: 
    650830        """ 
    651831        # Table properties 
     
    679859 
    680860            # Potential multishell params 
    681             #length_control = param.length_control 
    682             #if length_control in param.name: 
    683  
    684861            checked_list = ["Distribution of "+param.name, str(param.default), 
    685                             str(param.limits[0]),str(param.limits[1]), 
     862                            str(param.limits[0]), str(param.limits[1]), 
    686863                            "35", "3", ""] 
    687864            self.addCheckedListToModel(self._poly_model, checked_list) 
     
    689866            #TODO: Need to find cleaner way to input functions 
    690867            func = QtGui.QComboBox() 
    691             func.addItems(['rectangle','array','lognormal','gaussian','schulz',]) 
    692             func_index = self.lstPoly.model().index(row,6) 
    693             self.lstPoly.setIndexWidget(func_index,func) 
     868            func.addItems(['rectangle', 'array', 'lognormal', 'gaussian', 'schulz',]) 
     869            func_index = self.lstPoly.model().index(row, 6) 
     870            self.lstPoly.setIndexWidget(func_index, func) 
    694871 
    695872        self.addPolyHeadersToModel(self._poly_model) 
     
    767944                    # Find param in volume_params 
    768945                    for p in self.model_parameters.form_volume_parameters: 
    769                         if p.name == par.name: 
    770                             item1_2 = QtGui.QStandardItem(str(p.default)) 
    771                             item1_3 = QtGui.QStandardItem(str(p.limits[0])) 
    772                             item1_4 = QtGui.QStandardItem(str(p.limits[1])) 
    773                             item1_5 = QtGui.QStandardItem(p.units) 
    774                             poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 
    775                             break 
     946                        if p.name != par.name: 
     947                            continue 
     948                        item1_2 = QtGui.QStandardItem(str(p.default)) 
     949                        item1_3 = QtGui.QStandardItem(str(p.limits[0])) 
     950                        item1_4 = QtGui.QStandardItem(str(p.limits[1])) 
     951                        item1_5 = QtGui.QStandardItem(p.units) 
     952                        poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 
     953                        break 
    776954                    item1.appendRow([poly_item]) 
    777955 
  • src/sas/sasgui/perspectives/fitting/model_thread.py

    r934ce649 rcbcdd2c  
    9999        output[index_model] = value 
    100100        elapsed = time.time() - self.starttime 
    101         self.complete(image=output, 
    102                        data=self.data, 
    103                        page_id=self.page_id, 
    104                        model=self.model, 
    105                        state=self.state, 
    106                        toggle_mode_on=self.toggle_mode_on, 
    107                        elapsed=elapsed, 
    108                        index=index_model, 
    109                        fid=self.fid, 
    110                        qmin=self.qmin, 
    111                        qmax=self.qmax, 
    112                        weight=self.weight, 
    113                        #qstep=self.qstep, 
    114                        update_chisqr=self.update_chisqr, 
    115                        source=self.source) 
     101        #self.complete(image=output, 
     102        #               data=self.data, 
     103        #               page_id=self.page_id, 
     104        #               model=self.model, 
     105        #               state=self.state, 
     106        #               toggle_mode_on=self.toggle_mode_on, 
     107        #               elapsed=elapsed, 
     108        #               index=index_model, 
     109        #               fid=self.fid, 
     110        #               qmin=self.qmin, 
     111        #               qmax=self.qmax, 
     112        #               weight=self.weight, 
     113        #               #qstep=self.qstep, 
     114        #               update_chisqr=self.update_chisqr, 
     115        #               source=self.source) 
     116        return (output, 
     117                self.data, 
     118                self.page_id, 
     119                self.model, 
     120                self.state, 
     121                self.toggle_mode_on, 
     122                elapsed, 
     123                index_model, 
     124                self.fid, 
     125                self.qmin, 
     126                self.qmax, 
     127                self.weight, 
     128                self.update_chisqr, 
     129                self.source) 
    116130 
    117131 
     
    178192        elapsed = time.time() - self.starttime 
    179193 
    180         self.complete(x=self.data.x[index], y=output[index], 
    181                       page_id=self.page_id, 
    182                       state=self.state, 
    183                       weight=self.weight, 
    184                       fid=self.fid, 
    185                       toggle_mode_on=self.toggle_mode_on, 
    186                       elapsed=elapsed, index=index, model=self.model, 
    187                       data=self.data, 
    188                       update_chisqr=self.update_chisqr, 
    189                       source=self.source) 
     194        #self.complete(x=self.data.x[index], y=output[index], 
     195        #              page_id=self.page_id, 
     196        #              state=self.state, 
     197        #              weight=self.weight, 
     198        #              fid=self.fid, 
     199        #              toggle_mode_on=self.toggle_mode_on, 
     200        #              elapsed=elapsed, index=index, model=self.model, 
     201        #              data=self.data, 
     202        #              update_chisqr=self.update_chisqr, 
     203        #              source=self.source) 
     204        return (self.data.x[index], output[index], 
     205                self.page_id, 
     206                self.state, 
     207                self.weight, 
     208                self.fid, 
     209                self.toggle_mode_on, 
     210                elapsed, index, self.model, 
     211                self.data, 
     212                self.update_chisqr, 
     213                self.source) 
    190214 
    191215    def results(self): 
Note: See TracChangeset for help on using the changeset viewer.