Changeset 57be490 in sasview


Ignore:
Timestamp:
May 17, 2018 4:50:09 AM (3 months ago)
Author:
Piotr Rozyczko <rozyczko@…>
Branches:
ESS_GUI, ESS_GUI_beta_approx, ESS_GUI_iss957, ESS_GUI_iss959, ESS_GUI_iss971, ESS_GUI_iss976
Children:
2495513
Parents:
976978b
git-author:
Piotr Rozyczko <rozyczko@…> (04/13/18 09:34:43)
git-committer:
Piotr Rozyczko <rozyczko@…> (05/17/18 04:50:09)
Message:

Merged ESS_GUI_reporting

Location:
src/sas/qtgui
Files:
4 added
7 edited

Legend:

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

    r01ef3f7 r57be490  
    4949from Utilities.UnitTesting import TabbedModelEditorTest 
    5050from Utilities.UnitTesting import AddMultEditorTest 
     51from Utilities.UnitTesting import ReportDialogTest 
    5152 
    5253# Unit Testing 
     
    109110        unittest.makeSuite(TabbedModelEditorTest.TabbedModelEditorTest,'test'), 
    110111        unittest.makeSuite(AddMultEditorTest.AddMultEditorTest, 'test'), 
     112        unittest.makeSuite(ReportDialogTest.ReportDialogTest,     'test'), 
    111113 
    112114        # Calculators 
  • src/sas/qtgui/MainWindow/GuiManager.py

    rc889a3e r57be490  
    2323from sas.qtgui.Utilities.GridPanel import BatchOutputPanel 
    2424 
     25from sas.qtgui.Utilities.ReportDialog import ReportDialog 
    2526from sas.qtgui.MainWindow.UI.AcknowledgementsUI import Ui_Acknowledgements 
    2627from sas.qtgui.MainWindow.AboutBox import AboutBox 
     
    488489    def actionSave_Analysis(self): 
    489490        """ 
    490         """ 
    491         print("actionSave_Analysis TRIGGERED") 
    492  
    493         pass 
     491        Menu File/Save Analysis 
     492        """ 
     493        self.communicate.saveAnalysisSignal.emit() 
    494494 
    495495    def actionQuit(self): 
     
    526526    def actionReport(self): 
    527527        """ 
    528         """ 
    529         print("actionReport TRIGGERED") 
    530         pass 
     528        Show the Fit Report dialog. 
     529        """ 
     530        report_list = None 
     531        if getattr(self._current_perspective, "currentTab"): 
     532            try: 
     533                report_list = self._current_perspective.currentTab.getReport() 
     534            except Exception as ex: 
     535                logging.error("Report generation failed with: " + str(ex)) 
     536 
     537        if report_list is not None: 
     538            self.report_dialog = ReportDialog(parent=self, report_list=report_list) 
     539            self.report_dialog.show() 
    531540 
    532541    def actionReset(self): 
  • src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py

    r3b3b40b r57be490  
    3737        self.maxIndex = 0 
    3838 
    39         # Index of the current tab 
    40         self.currentTab = 0 
     39        ## Index of the current tab 
     40        #self.currentTab = 0 
    4141 
    4242        # The default optimizer 
     
    318318 
    319319        pass 
     320 
     321    @property 
     322    def currentTab(self): 
     323        """ 
     324        Returns the tab widget currently shown 
     325        """ 
     326        return self.currentWidget() 
     327 
  • src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py

    rb5cc06e r57be490  
    6868    multishell_parameters = getIterParams(parameters) 
    6969    multishell_param_name, _ = getMultiplicity(parameters) 
     70 
    7071    if is2D: 
    7172        params = [p for p in parameters.kernel_parameters if p.type != 'magnetic'] 
     
    443444 
    444445 
     446def getStandardParam(model=None): 
     447    """ 
     448    Returns a list with standard parameters for the current model 
     449    """ 
     450    param = [] 
     451    num_rows = model.rowCount() 
     452    if num_rows < 1: 
     453        return None 
     454 
     455    for row in range(num_rows): 
     456        param_name = model.item(row, 0).text() 
     457        checkbox_state = model.item(row,0).checkState() == QtCore.Qt.Checked 
     458        value= model.item(row, 1).text() 
     459        column_shift = 0 
     460        if model.columnCount() == 5: # no error column 
     461            error_state = False 
     462            error_value = 0.0 
     463        else: 
     464            error_state = True 
     465            error_value = model.item(row, 2).text() 
     466            column_shift = 1 
     467        min_state = True 
     468        max_state = True 
     469        min_value = model.item(row, 2+column_shift).text() 
     470        max_value = model.item(row, 3+column_shift).text() 
     471        unit = "" 
     472        if model.item(row, 4+column_shift) is not None: 
     473            unit = model.item(row, 4+column_shift).text() 
     474 
     475        param.append([checkbox_state, param_name, value, "", 
     476                        [error_state, error_value], 
     477                        [min_state, min_value], 
     478                        [max_state, max_value], unit]) 
     479 
     480    return param 
     481 
     482def getOrientationParam(kernel_module=None): 
     483    """ 
     484    Get the dictionary with orientation parameters 
     485    """ 
     486    param = [] 
     487    if kernel_module is None:  
     488        return None 
     489    for param_name in list(kernel_module.params.keys()): 
     490        name = param_name 
     491        value = kernel_module.params[param_name] 
     492        min_state = True 
     493        max_state = True 
     494        error_state = False 
     495        error_value = 0.0 
     496        checkbox_state = True #?? 
     497        details = kernel_module.details[param_name] #[unit, mix, max] 
     498        param.append([checkbox_state, name, value, "", 
     499                     [error_state, error_value], 
     500                     [min_state, details[1]], 
     501                     [max_state, details[2]], details[0]]) 
     502 
     503    return param 
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    raed0532 r57be490  
    11import json 
    22import os 
     3import copy 
    34from collections import defaultdict 
    45 
     
    2122 
    2223from sas.sascalc.fit.BumpsFitting import BumpsFit as Fit 
     24from sas.sascalc.fit.pagestate import PageState 
    2325 
    2426import sas.qtgui.Utilities.GuiUtils as GuiUtils 
     
    4547from sas.qtgui.Perspectives.Fitting.Constraint import Constraint 
    4648from sas.qtgui.Perspectives.Fitting.MultiConstraint import MultiConstraint 
     49from sas.qtgui.Perspectives.Fitting.ReportPageLogic import ReportPageLogic 
     50 
    4751 
    4852 
     
    506510        # Signals from other widgets 
    507511        self.communicate.customModelDirectoryChanged.connect(self.onCustomModelChange) 
     512        self.communicate.saveAnalysisSignal.connect(self.savePageState) 
     513        #self.communicate.saveReportSignal.connect(self.saveReport) 
    508514 
    509515    def modelName(self): 
     
    26332639            self.page_stack.pop() 
    26342640 
     2641    def getReport(self): 
     2642        """ 
     2643        Create and return HTML report with parameters and charts 
     2644        """ 
     2645        index = None 
     2646        if self.all_data: 
     2647            index = self.all_data[self.data_index] 
     2648        report_logic = ReportPageLogic(self, 
     2649                                       kernel_module=self.kernel_module, 
     2650                                       data=self.data, 
     2651                                       index=index, 
     2652                                       model=self._model_model) 
     2653 
     2654        return report_logic.reportList() 
     2655 
     2656    def savePageState(self): 
     2657        """ 
     2658        Create and serialize local PageState 
     2659        """ 
     2660        from sas.sascalc.fit.pagestate import Reader 
     2661        model = self.kernel_module 
     2662 
     2663        # Old style PageState object 
     2664        state = PageState(model=model, data=self.data) 
     2665 
     2666        # Add parameter data to the state 
     2667        self.getCurrentFitState(state) 
     2668 
     2669        # Create the filewriter, aptly named 'Reader' 
     2670        state_reader = Reader(self.loadPageStateCallback) 
     2671        filepath = self.saveAsAnalysisFile() 
     2672        if filepath is None: 
     2673            return 
     2674        state_reader.write(filename=filepath, fitstate=state) 
     2675        pass 
     2676 
     2677    def saveAsAnalysisFile(self): 
     2678        """ 
     2679        Show the save as... dialog and return the chosen filepath 
     2680        """ 
     2681        default_name = "FitPage"+str(self.tab_id)+".fitv" 
     2682 
     2683        wildcard = "fitv files (*.fitv)" 
     2684        kwargs = { 
     2685            'caption'   : 'Save As', 
     2686            'directory' : default_name, 
     2687            'filter'    : wildcard, 
     2688            'parent'    : None, 
     2689        } 
     2690        # Query user for filename. 
     2691        filename_tuple = QtWidgets.QFileDialog.getSaveFileName(**kwargs) 
     2692        filename = filename_tuple[0] 
     2693        return filename 
     2694 
     2695    def loadPageStateCallback(self,state=None, datainfo=None, format=None): 
     2696        """ 
     2697        This is a callback method called from the CANSAS reader. 
     2698        We need the instance of this reader only for writing out a file, 
     2699        so there's nothing here. 
     2700        Until Load Analysis is implemented, that is. 
     2701        """ 
     2702        pass 
     2703 
     2704    def loadPageState(self, pagestate=None): 
     2705        """ 
     2706        Load the PageState object and update the current widget 
     2707        """ 
     2708        pass 
     2709 
     2710    def getCurrentFitState(self, state=None): 
     2711        """ 
     2712        Store current state for fit_page 
     2713        """ 
     2714        # save model option 
     2715        #if self.model is not None: 
     2716        #    self.disp_list = self.getDispParamList() 
     2717        #    state.disp_list = copy.deepcopy(self.disp_list) 
     2718        #    #state.model = self.model.clone() 
     2719 
     2720        # Comboboxes 
     2721        state.categorycombobox = self.cbCategory.currentText() 
     2722        state.formfactorcombobox = self.cbModel.currentText() 
     2723        if self.cbStructureFactor.isEnabled(): 
     2724            state.structureCombobox = self.cbStructureFactor.currentText() 
     2725        state.tcChi = self.chi2 
     2726 
     2727        state.enable2D = self.is2D 
     2728 
     2729        #state.weights = copy.deepcopy(self.weights) 
     2730        # save data 
     2731        state.data = copy.deepcopy(self.data) 
     2732 
     2733        # save plotting range 
     2734        state.qmin = self.q_range_min 
     2735        state.qmax = self.q_range_max 
     2736        state.npts = self.npts 
     2737 
     2738        #    self.state.enable_disp = self.enable_disp.GetValue() 
     2739        #    self.state.disable_disp = self.disable_disp.GetValue() 
     2740 
     2741        #    self.state.enable_smearer = \ 
     2742        #                        copy.deepcopy(self.enable_smearer.GetValue()) 
     2743        #    self.state.disable_smearer = \ 
     2744        #                        copy.deepcopy(self.disable_smearer.GetValue()) 
     2745 
     2746        #self.state.pinhole_smearer = \ 
     2747        #                        copy.deepcopy(self.pinhole_smearer.GetValue()) 
     2748        #self.state.slit_smearer = copy.deepcopy(self.slit_smearer.GetValue()) 
     2749        #self.state.dI_noweight = copy.deepcopy(self.dI_noweight.GetValue()) 
     2750        #self.state.dI_didata = copy.deepcopy(self.dI_didata.GetValue()) 
     2751        #self.state.dI_sqrdata = copy.deepcopy(self.dI_sqrdata.GetValue()) 
     2752        #self.state.dI_idata = copy.deepcopy(self.dI_idata.GetValue()) 
     2753 
     2754        p = self.model_parameters 
     2755        # save checkbutton state and txtcrtl values 
     2756        state.parameters = FittingUtilities.getStandardParam() 
     2757        state.orientation_params_disp = FittingUtilities.getOrientationParam() 
     2758 
     2759        #self._copy_parameters_state(self.orientation_params_disp, self.state.orientation_params_disp) 
     2760        #self._copy_parameters_state(self.parameters, self.state.parameters) 
     2761        #self._copy_parameters_state(self.fittable_param, self.state.fittable_param) 
     2762        #self._copy_parameters_state(self.fixed_param, self.state.fixed_param) 
     2763 
     2764 
  • src/sas/qtgui/Utilities/GuiUtils.py

    rd4dac80 r57be490  
     1# -*- coding: utf-8 -*- 
    12""" 
    23Global defaults and various utility functions usable by the general GUI 
     
    248249    sendDataToGridSignal = QtCore.pyqtSignal(list) 
    249250 
     251    # Action Save Analysis triggered 
     252    saveAnalysisSignal = QtCore.pyqtSignal() 
    250253 
    251254def updateModelItemWithPlot(item, update_data, name=""): 
     
    378381                 if str(i.text()) == filename]) 
    379382    return item[0] if len(item)>0 else None 
     383 
     384def plotsFromModel(model_name, model_item): 
     385    """ 
     386    Returns the list of plots for the item with model name in the model 
     387    """ 
     388    assert isinstance(model_item, QtGui.QStandardItem) 
     389    assert isinstance(model_name, str) 
     390 
     391    plot_data = [] 
     392    # Iterate over model looking for named items 
     393    for index in range(model_item.rowCount()): 
     394        item = model_item.child(index) 
     395        if isinstance(item.data(), (Data1D, Data2D)): 
     396            plot_data.append(item.data()) 
     397        if model_name in str(item.text()): 
     398            #plot_data.append(item.child(0).data()) 
     399            # Going 1 level deeper only 
     400            for index_2 in range(item.rowCount()): 
     401                item_2 = item.child(index_2) 
     402                if item_2 and isinstance(item_2.data(), (Data1D, Data2D)): 
     403                    plot_data.append(item_2.data()) 
     404 
     405    return plot_data 
    380406 
    381407def plotsFromFilename(filename, model_item): 
     
    841867    return output.lstrip().rstrip() 
    842868 
     869def replaceHTMLwithUTF8(html): 
     870    """ 
     871    Replace some important HTML-encoded characters 
     872    with their UTF-8 equivalents 
     873    """ 
     874    # Angstrom 
     875    html_out = html.replace("&#x212B;", "à
     876") 
     877    # infinity 
     878    html_out = html_out.replace("&#x221e;", "∞") 
     879    # +/- 
     880    html_out = html_out.replace("&#177;", "±") 
     881 
     882    return html_out 
     883 
     884def replaceHTMLwithASCII(html): 
     885    """ 
     886    Replace some important HTML-encoded characters 
     887    with their ASCII equivalents 
     888    """ 
     889    # Angstrom 
     890    html_out = html.replace("&#x212B;", "Ang") 
     891    # infinity 
     892    html_out = html_out.replace("&#x221e;", "inf") 
     893    # +/- 
     894    html_out = html_out.replace("&#177;", "+/-") 
     895 
     896    return html_out 
     897 
     898def convertUnitToUTF8(unit): 
     899    """ 
     900    Convert ASCII unit display into UTF-8 symbol 
     901    """ 
     902    if unit == "1/A": 
     903        return "à
     904<sup>-1</sup>" 
     905    elif unit == "1/cm": 
     906        return "cm<sup>-1</sup>" 
     907    elif unit == "Ang": 
     908        return "à
     909" 
     910    elif unit == "1e-6/Ang^2": 
     911        return "10<sup>-6</sup>/à
     912<sup>2</sup>" 
     913    elif unit == "inf": 
     914        return "∞" 
     915    elif unit == "-inf": 
     916        return "-∞" 
     917    else: 
     918        return unit 
     919 
    843920def convertUnitToHTML(unit): 
    844921    """ 
  • src/sas/qtgui/Utilities/UnitTesting/GuiUtilsTest.py

    r6cb305a r57be490  
     1# -*- coding: utf-8 -*- 
    12import sys 
    23import unittest 
     
    446447        self.assertEqual(yscale, "log") 
    447448 
     449    def testReplaceHTMLwithUTF8(self): 
     450        ''' test single character replacement ''' 
     451        s = None 
     452        with self.assertRaises(AttributeError): 
     453            result = replaceHTMLwithUTF8(s) 
     454 
     455        s = "" 
     456        self.assertEqual(replaceHTMLwithUTF8(s), s) 
     457 
     458        s = "aaaa" 
     459        self.assertEqual(replaceHTMLwithUTF8(s), s) 
     460 
     461        s = "&#x212B; &#x221e;      &#177;" 
     462        self.assertEqual(replaceHTMLwithUTF8(s), "à
     463 âˆž      ±") 
     464 
     465    def testReplaceHTMLwithASCII(self): 
     466        ''' test single character replacement''' 
     467        s = None 
     468        with self.assertRaises(AttributeError): 
     469            result = replaceHTMLwithASCII(s) 
     470 
     471        s = "" 
     472        self.assertEqual(replaceHTMLwithASCII(s), s) 
     473 
     474        s = "aaaa" 
     475        self.assertEqual(replaceHTMLwithASCII(s), s) 
     476 
     477        s = "&#x212B; &#x221e;      &#177;" 
     478        self.assertEqual(replaceHTMLwithASCII(s), "Ang inf      +/-") 
     479 
     480    def testConvertUnitToUTF8(self): 
     481        ''' test unit string replacement''' 
     482        s = None 
     483        self.assertIsNone(convertUnitToUTF8(s)) 
     484 
     485        s = "" 
     486        self.assertEqual(convertUnitToUTF8(s), s) 
     487 
     488        s = "aaaa" 
     489        self.assertEqual(convertUnitToUTF8(s), s) 
     490 
     491        s = "1/A" 
     492        self.assertEqual(convertUnitToUTF8(s), "à
     493<sup>-1</sup>") 
     494 
     495        s = "Ang" 
     496        self.assertEqual(convertUnitToUTF8(s), "à
     497") 
     498 
     499        s = "1e-6/Ang^2" 
     500        self.assertEqual(convertUnitToUTF8(s), "10<sup>-6</sup>/à
     501<sup>2</sup>") 
     502 
     503        s = "inf" 
     504        self.assertEqual(convertUnitToUTF8(s), "∞") 
     505 
     506        s = "1/cm" 
     507        self.assertEqual(convertUnitToUTF8(s), "cm<sup>-1</sup>") 
     508 
     509    def testConvertUnitToHTML(self): 
     510        ''' test unit string replacement''' 
     511        s = None 
     512        self.assertIsNone(convertUnitToHTML(s)) 
     513 
     514        s = "" 
     515        self.assertEqual(convertUnitToHTML(s), s) 
     516 
     517        s = "aaaa" 
     518        self.assertEqual(convertUnitToHTML(s), s) 
     519 
     520        s = "1/A" 
     521        self.assertEqual(convertUnitToHTML(s), "&#x212B;<sup>-1</sup>") 
     522 
     523        s = "Ang" 
     524        self.assertEqual(convertUnitToHTML(s), "&#x212B;") 
     525 
     526        s = "1e-6/Ang^2" 
     527        self.assertEqual(convertUnitToHTML(s), "10<sup>-6</sup>/&#x212B;<sup>2</sup>") 
     528 
     529        s = "inf" 
     530        self.assertEqual(convertUnitToHTML(s), "&#x221e;") 
     531        s = "-inf" 
     532 
     533        self.assertEqual(convertUnitToHTML(s), "-&#x221e;") 
     534 
     535        s = "1/cm" 
     536        self.assertEqual(convertUnitToHTML(s), "cm<sup>-1</sup>") 
     537 
    448538    def testParseName(self): 
    449539        '''test parse out a string from the beinning of a string''' 
Note: See TracChangeset for help on using the changeset viewer.