Changes in / [75906a1:d00475d] in sasview


Ignore:
Location:
src/sas/qtgui
Files:
8 edited

Legend:

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

    r6bc0840 r6bc0840  
    233233        filename = QtWidgets.QFileDialog.getOpenFileName(**kwargs)[0] 
    234234        if filename: 
    235             load_thread = threads.deferToThread(self.readProject, filename) 
    236             load_thread.addCallback(self.readProjectComplete) 
    237             load_thread.addErrback(self.readProjectFailed) 
    238  
    239     def loadFailed(self, reason): 
    240         """ 
    241         """ 
    242         print("file load FAILED: ", reason) 
    243         pass 
    244  
    245     def readProjectFailed(self, reason): 
    246         """ 
    247         """ 
    248         print("readProjectFailed FAILED: ", reason) 
    249         pass 
    250  
    251     def readProject(self, filename): 
    252         self.communicator.statusBarUpdateSignal.emit("Loading Project... %s" % os.path.basename(filename)) 
    253         try: 
    254             manager = DataManager() 
    255             with open(filename, 'r') as infile: 
    256                 manager.load_from_readable(infile) 
    257  
    258             self.communicator.statusBarUpdateSignal.emit("Loaded Project: %s" % os.path.basename(filename)) 
    259             return manager 
    260  
    261         except: 
    262             self.communicator.statusBarUpdateSignal.emit("Failed: %s" % os.path.basename(filename)) 
    263             raise 
    264  
    265     def readProjectComplete(self, manager): 
    266         self.model.clear() 
    267  
    268         self.manager.assign(manager) 
    269         self.model.beginResetModel() 
    270         for id, item in self.manager.get_all_data().items(): 
    271             self.updateModel(item.data, item.path) 
    272  
    273         self.model.endResetModel() 
     235            self.readProject(filename) 
     236 
     237    def loadAnalysis(self): 
     238        """ 
     239        Called when the "Open Analysis" menu item chosen. 
     240        """ 
     241        kwargs = { 
     242            'parent'    : self, 
     243            'caption'   : 'Open Analysis', 
     244            'filter'    : 'Project (*.fitv);;All files (*.*)', 
     245            'options'   : QtWidgets.QFileDialog.DontUseNativeDialog 
     246        } 
     247        filename = QtWidgets.QFileDialog.getOpenFileName(**kwargs)[0] 
     248        if filename: 
     249            self.readAnalysis(filename) 
    274250 
    275251    def saveProject(self): 
     
    285261        name_tuple = QtWidgets.QFileDialog.getSaveFileName(**kwargs) 
    286262        filename = name_tuple[0] 
    287         if filename: 
    288             _, extension = os.path.splitext(filename) 
    289             if not extension: 
    290                 filename = '.'.join((filename, 'json')) 
    291             self.communicator.statusBarUpdateSignal.emit("Saving Project... %s\n" % os.path.basename(filename)) 
    292             with open(filename, 'w') as outfile: 
    293                 self.manager.save_to_writable(outfile) 
     263        if not filename: 
     264            return 
     265        _, extension = os.path.splitext(filename) 
     266        if not extension: 
     267            filename = '.'.join((filename, 'json')) 
     268        self.communicator.statusBarUpdateSignal.emit("Saving Project... %s\n" % os.path.basename(filename)) 
     269 
     270        return filename 
     271 
     272    def saveAsAnalysisFile(self, tab_id=1): 
     273        """ 
     274        Show the save as... dialog and return the chosen filepath 
     275        """ 
     276        default_name = "FitPage"+str(tab_id)+".fitv" 
     277 
     278        wildcard = "fitv files (*.fitv)" 
     279        kwargs = { 
     280            'caption'   : 'Save As', 
     281            'directory' : default_name, 
     282            'filter'    : wildcard, 
     283            'parent'    : None, 
     284        } 
     285        # Query user for filename. 
     286        filename_tuple = QtWidgets.QFileDialog.getSaveFileName(**kwargs) 
     287        filename = filename_tuple[0] 
     288        return filename 
     289 
     290    def saveAnalysis(self, data, tab_id=1): 
     291        """ 
     292        Called when the "Save Analysis" menu item chosen. 
     293        """ 
     294        filename = self.saveAsAnalysisFile(tab_id) 
     295        if not filename: 
     296            return 
     297        _, extension = os.path.splitext(filename) 
     298        if not extension: 
     299            filename = '.'.join((filename, 'fitv')) 
     300        self.communicator.statusBarUpdateSignal.emit("Saving analysis... %s\n" % os.path.basename(filename)) 
     301 
     302        with open(filename, 'w') as outfile: 
     303            GuiUtils.saveData(outfile, data) 
     304 
     305        self.communicator.statusBarUpdateSignal.emit('Analysis saved.') 
     306 
     307    def allDataForModel(self, model): 
     308        # data model 
     309        all_data = {} 
     310        for i in range(model.rowCount()): 
     311            properties = {} 
     312            item = model.item(i) 
     313            data = GuiUtils.dataFromItem(item) 
     314            if data is None: continue 
     315            # Now, all plots under this item 
     316            filename = data.filename 
     317            is_checked = item.checkState() 
     318            properties['checked'] = is_checked 
     319            other_datas = [] 
     320            # no need to save other_datas - things will be refit on read 
     321            #other_datas = GuiUtils.plotsFromFilename(filename, model) 
     322            # skip the main plot 
     323            #other_datas = list(other_datas.values())[1:] 
     324            all_data[data.id] = [data, properties, other_datas] 
     325        return all_data 
     326 
     327    def getDataForID(self, id): 
     328        # return the dataset with the given ID 
     329        all_data = [] 
     330        for model in (self.model, self.theory_model): 
     331            for i in range(model.rowCount()): 
     332                properties = {} 
     333                item = model.item(i) 
     334                data = GuiUtils.dataFromItem(item) 
     335                if data is None: continue 
     336                if data.id != id: continue 
     337                # We found the dataset - save it. 
     338                filename = data.filename 
     339                is_checked = item.checkState() 
     340                properties['checked'] = is_checked 
     341                other_datas = GuiUtils.plotsFromFilename(filename, model) 
     342                # skip the main plot 
     343                other_datas = list(other_datas.values())[1:] 
     344                all_data = [data, properties, other_datas] 
     345                break 
     346        return all_data 
     347 
     348    def getAllData(self): 
     349        """ 
     350        converts all datasets into serializable dictionary 
     351        """ 
     352        data = self.allDataForModel(self.model) 
     353        theory = self.allDataForModel(self.theory_model) 
     354 
     355        all_data = {} 
     356        for key, value in data.items(): 
     357            all_data[key] = value 
     358        for key, value in theory.items(): 
     359            if key in all_data: 
     360                raise ValueError("Inconsistent data in Project file.") 
     361            all_data[key] = value 
     362        return all_data 
     363 
     364    def saveDataToFile(self, outfile): 
     365        """ 
     366        Save every dataset to a json file 
     367        """ 
     368        all_data = self.getAllData() 
     369        # save datas 
     370        GuiUtils.saveData(outfile, all_data) 
     371 
     372    def readProject(self, filename): 
     373        """ 
     374        Read out datasets and fitpages from file 
     375        """ 
     376        with open(filename, 'r') as infile: 
     377            all_data = GuiUtils.readDataFromFile(infile) 
     378 
     379        for key, value in all_data.items(): 
     380            data_dict = {key:value['fit_data']} 
     381            items = self.updateModelFromData(data_dict) 
     382            # send newly created item to its perspective 
     383            if 'fit_params' in value: 
     384                self.sendItemToPerspective(items[0]) 
     385                # Make the perspective read the rest of the read data 
     386                self._perspective().updateFromParameters(value['fit_params']) 
     387 
     388        pass # debugger 
     389 
     390    def readAnalysis(self, filename): 
     391        """ 
     392        Read out a single dataset and fitpage from file 
     393        """ 
     394        with open(filename, 'r') as infile: 
     395            all_data = GuiUtils.readDataFromFile(infile) 
     396            # simulate full project structure 
     397            all_data_dict = {1:all_data['fit_data']} 
     398            items = self.updateModelFromData(all_data_dict) 
     399            # TODO: allow other perspectives 
     400            # send newly created item to its perspective 
     401            if len(items) > 0: 
     402                self.sendItemToPerspective(items[0]) 
     403            # Make the perspective read the rest of the read data 
     404            self._perspective().updateFromParameters(all_data['fit_params']) 
     405 
     406            pass 
     407 
     408    def updateModelFromData(self, data): 
     409        """ 
     410        Given data from analysis/project file, 
     411        create indices and populate data/theory models 
     412        """ 
     413        # model items for top level datasets 
     414        items = [] 
     415        #self.model.beginResetModel() 
     416        for key, value in data.items(): 
     417            # key - cardinal number of dataset 
     418            # value - main dataset, [dependant filesets] 
     419            # add the main index 
     420            if not value: continue 
     421            new_data = value[0] 
     422            assert isinstance(new_data, (Data1D, Data2D)) 
     423            properties = value[1] 
     424            is_checked = properties['checked'] 
     425            new_item = GuiUtils.createModelItemWithPlot(new_data, new_data.filename) 
     426            new_item.setCheckState(is_checked) 
     427            items.append(new_item) 
     428            model = self.theory_model 
     429            if new_data.is_data: 
     430                model = self.model 
     431            model.appendRow(new_item) 
     432            self.manager.add_data(data_list={new_data.id:new_data}) 
     433 
     434            # Add the underlying data 
     435            if not value[2]: 
     436                continue 
     437            for plot in value[2]: 
     438                assert isinstance(plot, (Data1D, Data2D)) 
     439                GuiUtils.updateModelItemWithPlot(new_item, plot, plot.name) 
     440        return items 
    294441 
    295442    def deleteFile(self, event): 
     
    410557            retval = msgbox.exec_() 
    411558 
     559    def sendItemToPerspective(self, item): 
     560        """ 
     561        Send the passed item data to the current perspective and set the relevant notifiers 
     562        """ 
     563        # Set the signal handlers 
     564        self.communicator.updateModelFromPerspectiveSignal.connect(self.updateModelFromPerspective) 
     565        selected_items = [item] 
     566        # Notify the GuiManager about the send request 
     567        try: 
     568            self._perspective().setData(data_item=selected_items, is_batch=False) 
     569        except Exception as ex: 
     570            msg = "%s perspective returned the following message: \n%s\n" %(self._perspective().name, str(ex)) 
     571            logging.error(msg) 
     572            msg = str(ex) 
     573            msgbox = QtWidgets.QMessageBox() 
     574            msgbox.setIcon(QtWidgets.QMessageBox.Critical) 
     575            msgbox.setText(msg) 
     576            msgbox.setStandardButtons(QtWidgets.QMessageBox.Ok) 
     577            retval = msgbox.exec_() 
    412578 
    413579    def freezeCheckedData(self): 
     
    14081574        checkbox_item.setCheckable(True) 
    14091575        checkbox_item.setCheckState(QtCore.Qt.Checked) 
    1410         checkbox_item.setText(os.path.basename(p_file)) 
     1576        if p_file is not None: 
     1577            checkbox_item.setText(os.path.basename(p_file)) 
    14111578 
    14121579        # Add the actual Data1D/Data2D object 
  • src/sas/qtgui/MainWindow/DataManager.py

    re2e5f3d r345b3b3  
    2929from sas.qtgui.Plotting.PlotterData import Data1D 
    3030from sas.qtgui.Plotting.PlotterData import Data2D 
    31 from sas.qtgui.Plotting.Plottables import Plottable 
    3231from sas.qtgui.Plotting.Plottables import PlottableTheory1D 
    3332from sas.qtgui.Plotting.Plottables import PlottableFit1D 
  • src/sas/qtgui/MainWindow/GuiManager.py

    r8748751 r8748751  
    251251        if self._current_perspective: 
    252252            self._current_perspective.setClosable() 
    253             #self._workspace.workspace.removeSubWindow(self._current_perspective) 
    254253            self._current_perspective.close() 
    255254            self._workspace.workspace.removeSubWindow(self._current_perspective) 
     
    555554        """ 
    556555        """ 
    557         print("actionOpen_Analysis TRIGGERED") 
     556        self.filesWidget.loadAnalysis() 
    558557        pass 
    559558 
     
    562561        Menu Save Project 
    563562        """ 
    564         self.filesWidget.saveProject() 
     563        filename = self.filesWidget.saveProject() 
     564 
     565        # datasets 
     566        all_data = self.filesWidget.getAllData() 
     567 
     568        # fit tabs 
     569        params = self.perspective().serializeAllFitpage() 
     570 
     571        # project dictionary structure: 
     572        # analysis[data.id] = [{"fit_data":[data, checkbox, child data], 
     573        #                       "fit_params":[fitpage_state]} 
     574        # "fit_params" not present if dataset not sent to fitting 
     575        analysis = {} 
     576 
     577        for id, data in all_data.items(): 
     578            data_content = {"fit_data":data} 
     579            if id in params.keys(): 
     580                # this dataset is represented also by the fit tab. Add to it. 
     581                data_content["fit_params"] = params[id] 
     582            analysis[id] = data_content 
     583 
     584        with open(filename, 'w') as outfile: 
     585            GuiUtils.saveData(outfile, analysis) 
    565586 
    566587    def actionSave_Analysis(self): 
     
    568589        Menu File/Save Analysis 
    569590        """ 
    570         self.communicate.saveAnalysisSignal.emit() 
     591        per = self.perspective() 
     592        if not isinstance(per, FittingWindow): 
     593            return 
     594        # get fit page serialization 
     595        params = per.serializeCurrentFitpage() 
     596        data_id = per.currentTabDataId() 
     597        tab_id = per.currentTab.tab_id 
     598        data = self.filesWidget.getDataForID(data_id) 
     599        analysis = {} 
     600        analysis['fit_data'] = data 
     601        analysis['fit_params'] = params 
     602 
     603        self.filesWidget.saveAnalysis(analysis, tab_id) 
     604 
     605        pass 
    571606 
    572607    def actionQuit(self): 
     
    10441079        """ 
    10451080        self._workspace.actionReport.setEnabled(False) 
     1081        self._workspace.actionOpen_Analysis.setEnabled(False) 
     1082        self._workspace.actionSave_Analysis.setEnabled(False) 
     1083        if hasattr(perspective, 'isSerializable') and perspective.isSerializable(): 
     1084            self._workspace.actionOpen_Analysis.setEnabled(True) 
     1085            self._workspace.actionSave_Analysis.setEnabled(True) 
     1086 
    10461087        if isinstance(perspective, Perspectives.PERSPECTIVES["Fitting"]): 
    10471088            self.checkAnalysisOption(self._workspace.actionFitting) 
  • src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py

    rd2007a8 ra3c59503  
    112112    def onLatexCopy(self): 
    113113        self.currentTab.onCopyToClipboard("Latex") 
     114 
     115    def serializeAllFitpage(self): 
     116        # serialize all active fitpages and return 
     117        # a dictionary: {data_id: fitpage_state} 
     118        params = {} 
     119        for i, tab in enumerate(self.tabs): 
     120            tab_data = self.getSerializedFitpage(tab) 
     121            if tab.tab_id is None: continue 
     122            id = tab_data['data_id'][0] 
     123            params[id] = tab_data 
     124        return params 
     125 
     126    def serializeCurrentFitpage(self): 
     127        # serialize current(active) fitpage 
     128        return self.getSerializedFitpage(self.currentTab) 
     129 
     130    def getSerializedFitpage(self, tab): 
     131        """ 
     132        get serialize requested fit tab 
     133        """ 
     134        fitpage_state = tab.getFitPage() 
     135        fitpage_state += tab.getFitModel() 
     136        # put the text into dictionary 
     137        line_dict = {} 
     138        for line in fitpage_state: 
     139            #content = line.split(',') 
     140            if len(line) > 1: 
     141                line_dict[line[0]] = line[1:] 
     142        return line_dict 
     143 
     144    def currentTabDataId(self): 
     145        """ 
     146        Returns the data ID of the current tab 
     147        """ 
     148        tab_id = None 
     149        if self.currentTab.data: 
     150            tab_id = self.currentTab.data.id 
     151        return tab_id 
     152 
     153    def updateFromParameters(self, parameters): 
     154        """ 
     155        Pass the update parameters to the current fit page 
     156        """ 
     157        self.currentTab.createPageForParameters(parameters) 
    114158 
    115159    def closeEvent(self, event): 
     
    258302        return True 
    259303 
     304    def isSerializable(self): 
     305        """ 
     306        Tell the caller that this perspective writes its state 
     307        """ 
     308        return True 
     309 
    260310    def setData(self, data_item=None, is_batch=False): 
    261311        """ 
     
    337387        pass 
    338388 
     389    def getCurrentStateAsXml(self): 
     390        """ 
     391        Returns an XML version of the current state 
     392        """ 
     393        state = {} 
     394        for tab in self.tabs: 
     395            pass 
     396        return state 
     397 
    339398    @property 
    340399    def currentTab(self): 
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    r75906a1 r75906a1  
    5252TAB_POLY = 3 
    5353CATEGORY_DEFAULT = "Choose category..." 
     54MODEL_DEFAULT = "Choose model..." 
    5455CATEGORY_STRUCTURE = "Structure Factor" 
    5556CATEGORY_CUSTOM = "Plugin Models" 
     
    566567        # Signals from other widgets 
    567568        self.communicate.customModelDirectoryChanged.connect(self.onCustomModelChange) 
    568         self.communicate.saveAnalysisSignal.connect(self.savePageState) 
    569         #self.communicate.loadAnalysisSignal.connect(self.loadPageState) 
    570569        self.smearing_widget.smearingChangedSignal.connect(self.onSmearingOptionsUpdate) 
    571570 
     
    10191018        model = self.cbModel.currentText() 
    10201019 
     1020        if model == MODEL_DEFAULT: 
     1021            # if the previous category was not the default, keep it. 
     1022            # Otherwise, just return 
     1023            if self._previous_model_index != 0: 
     1024                # We need to block signals, or else state changes on perceived unchanged conditions 
     1025                self.cbModel.blockSignals(True) 
     1026                self.cbModel.setCurrentIndex(self._previous_model_index) 
     1027                self.cbModel.blockSignals(False) 
     1028            return 
     1029 
    10211030        # Assure the control is active 
    10221031        if not self.cbModel.isEnabled(): 
     
    10261035            return 
    10271036        self.chkMagnetism.setEnabled(self.canHaveMagnetism()) 
     1037        self.chkMagnetism.setEnabled(self.canHaveMagnetism()) 
    10281038        self.tabFitting.setTabEnabled(TAB_MAGNETISM, self.chkMagnetism.isChecked() and self.canHaveMagnetism()) 
     1039        self._previous_model_index = self.cbModel.currentIndex() 
    10291040 
    10301041        # Reset parameters to fit 
     
    12001211            self._model_model.clear() 
    12011212            return 
    1202  
     1213        # Wipe out the parameter model 
     1214        self._model_model.clear() 
    12031215        # Safely clear and enable the model combo 
    12041216        self.cbModel.blockSignals(True) 
     
    12121224        model_list = self.master_category_dict[category] 
    12131225        # Populate the models combobox 
     1226        self.cbModel.blockSignals(True) 
     1227        self.cbModel.addItem(MODEL_DEFAULT) 
    12141228        self.cbModel.addItems(sorted([model for (model, _) in model_list])) 
     1229        self.cbModel.blockSignals(False) 
    12151230 
    12161231    def onPolyModelChange(self, top, bottom): 
     
    33733388        return report_logic.reportList() 
    33743389 
    3375     def savePageState(self): 
    3376         """ 
    3377         Create and serialize local PageState 
    3378         """ 
    3379         filepath = self.saveAsAnalysisFile() 
    3380         if filepath is None or filepath == "": 
    3381             return 
    3382  
    3383         fitpage_state = self.getFitPage() 
    3384         fitpage_state += self.getFitModel() 
    3385  
    3386         with open(filepath, 'w') as statefile: 
    3387             for line in fitpage_state: 
    3388                 statefile.write(str(line)) 
    3389  
    3390         self.communicate.statusBarUpdateSignal.emit('Analysis saved.') 
    3391  
    3392     def saveAsAnalysisFile(self): 
    3393         """ 
    3394         Show the save as... dialog and return the chosen filepath 
    3395         """ 
    3396         default_name = "FitPage"+str(self.tab_id)+".fitv" 
    3397  
    3398         wildcard = "fitv files (*.fitv)" 
    3399         kwargs = { 
    3400             'caption'   : 'Save As', 
    3401             'directory' : default_name, 
    3402             'filter'    : wildcard, 
    3403             'parent'    : None, 
    3404         } 
    3405         # Query user for filename. 
    3406         filename_tuple = QtWidgets.QFileDialog.getSaveFileName(**kwargs) 
    3407         filename = filename_tuple[0] 
    3408         return filename 
    3409  
    34103390    def loadPageStateCallback(self,state=None, datainfo=None, format=None): 
    34113391        """ 
     
    35263506        """ 
    35273507        param_list = [] 
     3508        if self.kernel_module is None: 
     3509            return param_list 
     3510 
    35283511        param_list.append(['model_name', str(self.cbModel.currentText())]) 
    35293512 
     
    36303613        cb_text = cb.text() 
    36313614 
    3632         context = {} 
    36333615        lines = cb_text.split(':') 
    36343616        if lines[0] != 'sasview_parameter_values': 
     
    36423624                line_dict[content[0]] = content[1:] 
    36433625 
     3626        self.updatePageWithParameters(line_dict) 
     3627 
     3628    def createPageForParameters(self, line_dict): 
     3629        """ 
     3630        Sets up page with requested model/str factor 
     3631        and fills it up with sent parameters 
     3632        """ 
     3633        if 'fitpage_category' in line_dict: 
     3634            self.cbCategory.setCurrentIndex(self.cbCategory.findText(line_dict['fitpage_category'][0])) 
     3635        if 'fitpage_model' in line_dict: 
     3636            self.cbModel.setCurrentIndex(self.cbModel.findText(line_dict['fitpage_model'][0])) 
     3637        if 'fitpage_structure' in line_dict: 
     3638            self.cbStructureFactor.setCurrentIndex(self.cbStructureFactor.findText(line_dict['fitpage_structure'][0])) 
     3639 
     3640        # Now that the page is ready for parameters, fill it up 
     3641        self.updatePageWithParameters(line_dict) 
     3642 
     3643    def updatePageWithParameters(self, line_dict): 
     3644        """ 
     3645        Update FitPage with parameters in line_dict 
     3646        """ 
     3647        if 'model_name' not in line_dict.keys(): 
     3648            return 
    36443649        model = line_dict['model_name'][0] 
    3645  
    3646         if 'model_name' not in line_dict.keys(): 
    3647             return False 
     3650        context = {} 
    36483651 
    36493652        if 'multiplicity' in line_dict.keys(): 
  • src/sas/qtgui/Perspectives/Fitting/UnitTesting/ComplexConstraintTest.py

    r725d9c06 r2eeda93  
    3434        category_index = self.tab1.cbCategory.findText("Shape Independent") 
    3535        self.tab1.cbCategory.setCurrentIndex(category_index) 
     36        model_index = self.tab1.cbModel.findText("be_polyelectrolyte") 
     37        self.tab1.cbModel.setCurrentIndex(model_index) 
     38 
    3639        category_index = self.tab2.cbCategory.findText("Cylinder") 
    3740        self.tab2.cbCategory.setCurrentIndex(category_index) 
     41        model_index = self.tab2.cbModel.findText("barbell") 
     42        self.tab2.cbModel.setCurrentIndex(model_index) 
    3843 
    3944        tabs = [self.tab1, self.tab2] 
  • src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py

    rd2007a8 r2eeda93  
    175175        category_index = self.widget.cbCategory.findText("Shape Independent") 
    176176        self.widget.cbCategory.setCurrentIndex(category_index) 
     177        model_index = self.widget.cbModel.findText("be_polyelectrolyte") 
     178        self.widget.cbModel.setCurrentIndex(model_index) 
    177179 
    178180        # test the model combo content 
    179         self.assertEqual(self.widget.cbModel.count(), 29) 
     181        self.assertEqual(self.widget.cbModel.count(), 30) 
    180182 
    181183        # Try to change back to default 
     
    201203        category_index = self.widget.cbCategory.findText("Shape Independent") 
    202204        self.widget.cbCategory.setCurrentIndex(category_index) 
     205        model_index = self.widget.cbModel.findText("be_polyelectrolyte") 
     206        self.widget.cbModel.setCurrentIndex(model_index) 
    203207 
    204208        # check the enablement of controls 
     
    215219        #  
    216220        # Now change the model 
    217         self.widget.cbModel.setCurrentIndex(3) 
     221        self.widget.cbModel.setCurrentIndex(4) 
    218222        self.assertEqual(self.widget.cbModel.currentText(),'dab') 
    219223 
     
    226230        self.widget.data_is_loaded = True 
    227231        # Reset the sasmodel index 
    228         self.widget.cbModel.setCurrentIndex(1) 
     232        self.widget.cbModel.setCurrentIndex(2) 
    229233        self.assertEqual(self.widget.cbModel.currentText(),'broad_peak') 
    230234 
     
    377381        category_index = self.widget.cbCategory.findText("Shape Independent") 
    378382        self.widget.cbCategory.setCurrentIndex(category_index) 
     383        model_index = self.widget.cbModel.findText("be_polyelectrolyte") 
     384        self.widget.cbModel.setCurrentIndex(model_index) 
     385 
    379386        # Check the poly model 
    380387        self.assertEqual(self.widget._poly_model.rowCount(), 0) 
     
    383390        # Change the category index so we have a model available 
    384391        self.widget.cbCategory.setCurrentIndex(2) 
     392        self.widget.cbModel.setCurrentIndex(1) 
    385393 
    386394        # Check the poly model 
     
    556564        category_index = self.widget.cbCategory.findText("Sphere") 
    557565        self.widget.cbCategory.setCurrentIndex(category_index) 
     566        model_index = self.widget.cbModel.findText("adsorbed_layer") 
     567        self.widget.cbModel.setCurrentIndex(model_index) 
    558568 
    559569        # Check the magnetic model 
     
    634644        category_index = self.widget.cbCategory.findText("Sphere") 
    635645        self.widget.cbCategory.setCurrentIndex(category_index) 
     646        model_index = self.widget.cbModel.findText("adsorbed_layer") 
     647        self.widget.cbModel.setCurrentIndex(model_index) 
    636648 
    637649        # Check the enablement/text 
     
    973985        category_index = self.widget.cbCategory.findText("Sphere") 
    974986        self.widget.cbCategory.setCurrentIndex(category_index) 
     987        model_index = self.widget.cbModel.findText("adsorbed_layer") 
     988        self.widget.cbModel.setCurrentIndex(model_index) 
    975989        self.widget.main_params_to_fit = ['scale'] 
    976990 
     
    9861000        self.assertListEqual(fp.main_params_to_fit, ['scale']) 
    9871001 
    988     def testPushFitPage(self): 
     1002    def notestPushFitPage(self): 
    9891003        """ 
    9901004        Push current state of fitpage onto stack 
     
    9971011        self.widget.data = item 
    9981012        category_index = self.widget.cbCategory.findText("Sphere") 
     1013        model_index = self.widget.cbModel.findText("adsorbed_layer") 
     1014        self.widget.cbModel.setCurrentIndex(model_index) 
    9991015 
    10001016        # Asses the initial state of stack 
  • src/sas/qtgui/Utilities/GuiUtils.py

    raed159f raed159f  
    1111import webbrowser 
    1212import urllib.parse 
     13import json 
     14from io import BytesIO 
    1315 
    1416import numpy as np 
     
    2628from sas.qtgui.Plotting.PlotterData import Data1D 
    2729from sas.qtgui.Plotting.PlotterData import Data2D 
     30from sas.qtgui.Plotting.Plottables import Plottable 
     31from sas.sascalc.dataloader.data_info import Sample, Source, Vector 
     32from sas.qtgui.Plotting.Plottables import View 
     33from sas.qtgui.Plotting.Plottables import PlottableTheory1D 
     34from sas.qtgui.Plotting.Plottables import PlottableFit1D 
     35from sas.qtgui.Plotting.Plottables import Text 
     36from sas.qtgui.Plotting.Plottables import Chisq 
     37from sas.qtgui.MainWindow.DataState import DataState 
     38 
    2839from sas.sascalc.dataloader.loader import Loader 
    2940from sas.qtgui.Utilities import CustomDir 
     
    257268    sendDataToGridSignal = QtCore.pyqtSignal(list) 
    258269 
    259     # Action Save Analysis triggered 
    260     saveAnalysisSignal = QtCore.pyqtSignal() 
    261  
    262270    # Mask Editor requested 
    263271    maskEditorSignal = QtCore.pyqtSignal(Data2D) 
     
    287295    resultPlotUpdateSignal = QtCore.pyqtSignal(list) 
    288296 
    289 def updateModelItemWithPlot(item, update_data, name=""): 
    290297    """ 
    291298    Adds a checkboxed row named "name" to QStandardItem 
     
    312319            # Force redisplay 
    313320            return 
    314  
    315321    # Create the new item 
    316322    checkbox_item = createModelItemWithPlot(update_data, name) 
    317323 
     324    if checkbox_state is not None: 
     325        checkbox_item.setCheckState(checkbox_state) 
    318326    # Append the new row to the main item 
    319327    item.appendRow(checkbox_item) 
     
    566574    if isinstance(data.process, list) and data.process: 
    567575        for process in data.process: 
     576            if process is None: 
     577                continue 
    568578            process_date = process.date 
    569579            process_date_item = QtGui.QStandardItem("Date: " + process_date) 
     
    11401150    return result 
    11411151 
     1152def saveData(fp, data): 
     1153    """ 
     1154    save content of data to fp (a .write()-supporting file-like object) 
     1155    """ 
     1156 
     1157    def add_type(dict, type): 
     1158        dict['__type__'] = type.__name__ 
     1159        return dict 
     1160 
     1161    def jdefault(o): 
     1162        """ 
     1163        objects that can't otherwise be serialized need to be converted 
     1164        """ 
     1165        # tuples and sets (TODO: default JSONEncoder converts tuples to lists, create custom Encoder that preserves tuples) 
     1166        if isinstance(o, (tuple, set)): 
     1167            content = { 'data': list(o) } 
     1168            return add_type(content, type(o)) 
     1169 
     1170        # "simple" types 
     1171        if isinstance(o, (Sample, Source, Vector)): 
     1172            return add_type(o.__dict__, type(o)) 
     1173        if isinstance(o, (Plottable, View)): 
     1174            return add_type(o.__dict__, type(o)) 
     1175 
     1176        # DataState 
     1177        if isinstance(o, (Data1D, Data2D)): 
     1178            # don't store parent 
     1179            content = o.__dict__.copy() 
     1180            #content.pop('parent') 
     1181            return add_type(content, type(o)) 
     1182 
     1183        # ndarray 
     1184        if isinstance(o, np.ndarray): 
     1185            buffer = BytesIO() 
     1186            np.save(buffer, o) 
     1187            buffer.seek(0) 
     1188            content = { 'data': buffer.read().decode('latin-1') } 
     1189            return add_type(content, type(o)) 
     1190 
     1191        # not supported 
     1192        logging.info("data cannot be serialized to json: %s" % type(o)) 
     1193        return None 
     1194 
     1195    json.dump(data, fp, indent=2, sort_keys=True, default=jdefault) 
     1196 
     1197def readDataFromFile(fp): 
     1198    ''' 
     1199    ''' 
     1200    supported = [ 
     1201        tuple, set, 
     1202        Sample, Source, Vector, 
     1203        Plottable, Data1D, Data2D, PlottableTheory1D, PlottableFit1D, Text, Chisq, View, 
     1204        DataState, np.ndarray] 
     1205 
     1206    lookup = dict((cls.__name__, cls) for cls in supported) 
     1207 
     1208    class TooComplexException(Exception): 
     1209        pass 
     1210 
     1211    def simple_type(cls, data, level): 
     1212        class Empty(object): 
     1213            def __init__(self): 
     1214                for key, value in data.items(): 
     1215                    setattr(self, key, generate(value, level)) 
     1216 
     1217        # create target object 
     1218        o = Empty() 
     1219        o.__class__ = cls 
     1220 
     1221        return o 
     1222 
     1223    def construct(type, data, level): 
     1224        try: 
     1225            cls = lookup[type] 
     1226        except KeyError: 
     1227            logging.info('unknown type: %s' % type) 
     1228            return None 
     1229 
     1230        # tuples and sets 
     1231        if cls in (tuple, set): 
     1232            # convert list to tuple/set 
     1233            return cls(generate(data['data'], level)) 
     1234 
     1235        # "simple" types 
     1236        if cls in (Sample, Source, Vector): 
     1237            return simple_type(cls, data, level) 
     1238        if issubclass(cls, Plottable) or (cls == View): 
     1239            return simple_type(cls, data, level) 
     1240 
     1241        # DataState 
     1242        if cls == DataState: 
     1243            o = simple_type(cls, data, level) 
     1244            o.parent = None # TODO: set to ??? 
     1245            return o 
     1246 
     1247        # ndarray 
     1248        if cls == np.ndarray: 
     1249            buffer = BytesIO() 
     1250            buffer.write(data['data'].encode('latin-1')) 
     1251            buffer.seek(0) 
     1252            return np.load(buffer) 
     1253 
     1254        logging.info('not implemented: %s, %s' % (type, cls)) 
     1255        return None 
     1256 
     1257    def generate(data, level): 
     1258        if level > 16: # recursion limit (arbitrary number) 
     1259            raise TooComplexException() 
     1260        else: 
     1261            level += 1 
     1262 
     1263        if isinstance(data, dict): 
     1264            try: 
     1265                type = data['__type__'] 
     1266            except KeyError: 
     1267                # if dictionary doesn't have __type__ then it is assumed to be just an ordinary dictionary 
     1268                o = {} 
     1269                for key, value in data.items(): 
     1270                    o[key] = generate(value, level) 
     1271                return o 
     1272 
     1273            return construct(type, data, level) 
     1274 
     1275        if isinstance(data, list): 
     1276            return [generate(item, level) for item in data] 
     1277 
     1278        return data 
     1279 
     1280    new_stored_data = {} 
     1281    for id, data in json.load(fp).items(): 
     1282        try: 
     1283            new_stored_data[id] = generate(data, 0) 
     1284        except TooComplexException: 
     1285            logging.info('unable to load %s' % id) 
     1286 
     1287    return new_stored_data 
     1288 
    11421289 
    11431290def enum(*sequential, **named): 
Note: See TracChangeset for help on using the changeset viewer.