source: sasview/src/sas/qtgui/Perspectives/Fitting/ReportPageLogic.py @ 085ee014

ESS_GUIESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 085ee014 was 085ee014, checked in by wojciech, 5 years ago

Removing tmp file handling from report logic to make it work on OSX

  • Property mode set to 100644
File size: 6.5 KB
Line 
1# -*- coding: utf-8 -*-
2import base64
3import datetime
4import re
5import sys
6import tempfile
7
8import logging
9from io import BytesIO
10import urllib.parse
11
12from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
13
14import sas.qtgui.Utilities.GuiUtils as GuiUtils
15from sas.qtgui.Perspectives.Fitting import FittingUtilities
16
17class ReportPageLogic(object):
18    """
19    Logic for the Report Page functionality. Refactored from FittingWidget.
20    """
21    def __init__(self, parent=None, kernel_module=None, data=None, index=None, model=None):
22
23        self.parent = parent
24        self.kernel_module = kernel_module
25        self.data = data
26        self._index = index
27        self.model = model
28
29    @staticmethod
30    def cleanhtml(raw_html):
31        """Remove html tags from a document"""
32        cleanr = re.compile('<.*?>')
33        cleantext = re.sub(cleanr, '', raw_html)
34        return cleantext
35
36    def reportList(self):
37        """
38        Return the HTML version of the full report
39        """
40        if self.kernel_module is None:
41            report_txt = "No model defined"
42            report_html = HEADER % report_txt
43            images = []
44            return [report_html, report_txt, images]
45
46        # Get plot image from plotpanel
47        images = self.getImages()
48
49        imagesHTML = ""
50        if images is not None:
51            imagesHTML = self.buildPlotsForReport(images)
52
53        report_header = self.reportHeader()
54
55        report_parameters = self.reportParams()
56
57        report_html = report_header + report_parameters + imagesHTML
58
59        report_txt = self.cleanhtml(report_html)
60
61        report_list = [report_html, report_txt, images]
62
63        return report_list
64
65    def reportHeader(self):
66        """
67        Look at widget state and extract report header info
68        """
69        report = ""
70
71        title = self.data.name
72        current_time = datetime.datetime.now().strftime("%I:%M%p, %B %d, %Y")
73        filename = self.data.filename
74        modelname = self.kernel_module.id
75        if hasattr(self.data, 'xmin'):
76            qrange_min = self.data.xmin
77            qrange_max = self.data.xmax
78        else:
79            qrange_min = min(self.data.x)
80            qrange_max = max(self.data.x)
81        qrange = "min = {}, max = {}".format(qrange_min, qrange_max)
82
83        title = title + " [" + current_time + "]"
84        title_name = HEADER % title
85        report = title_name
86        report = report + CENTRE % "File name:{}\n".format(filename)
87        report = report + CENTRE % "Model name:{}\n".format(modelname)
88        report = report + CENTRE % "Q Range: {}\n".format(qrange)
89        chi2_repr = GuiUtils.formatNumber(self.parent.chi2, high=True)
90        report = report + CENTRE % "Chi2/Npts:{}\n".format(chi2_repr)
91
92        return report
93
94    def buildPlotsForReport(self, images):
95        """ Convert Matplotlib figure 'fig' into a <img> tag for HTML use using base64 encoding. """
96        html = FEET_1 % self.data.filename
97
98        for fig in images:
99            canvas = FigureCanvas(fig)
100            png_output = BytesIO()
101            try:
102                fig.savefig(png_output, format="png", dpi=75)
103            except PermissionError as ex:
104                logging.error("Creating of the report failed: %s"%str(ex))
105                return
106            data64 = base64.b64encode(png_output.getvalue())
107            data_to_print = urllib.parse.quote(data64)
108            feet = FEET_2
109            if sys.platform == "darwin":  # Mac
110                feet = FEET_3
111            html += feet.format(data_to_print)
112            html += ELINE
113            png_output.close()
114            del canvas
115        return html
116
117    def reportParams(self):
118        """
119        Look at widget state and extract parameters
120        """
121        pars = FittingUtilities.getStandardParam(self.model)
122        if pars is None:
123            return ""
124
125        report = ""
126        plus_minus = " &#177; "
127        for value in pars:
128            try:
129                par_name = value[1]
130                par_fixed = not value[0]
131                par_value = value[2]
132                par_unit = value[7]
133                # Convert units for nice display
134                par_unit = GuiUtils.convertUnitToHTML(par_unit.strip())
135                if par_fixed:
136                    error = " (fixed)"
137                else:
138                    error = plus_minus + str(value[4][1])
139                param = par_name + " = " + par_value + error + " " + par_unit
140            except IndexError as ex:
141                # corrupted model. Complain and skip the line
142                logging.error("Error in parsing parameters: "+str(ex))
143                continue
144            report += CENTRE % param + "\n"
145
146        return report
147
148    def getImages(self):
149        """
150        Create MPL figures for the current fit
151        """
152        graphs = []
153        modelname = self.kernel_module.name
154        if not modelname or self._index is None:
155            return None
156        plot_ids = [plot.id for plot in GuiUtils.plotsFromModel(modelname, self._index)]
157
158        # Active plots
159        import sas.qtgui.Plotting.PlotHelper as PlotHelper
160        shown_plot_names = PlotHelper.currentPlots()
161
162        # current_plots = list of graph names of currently shown plots
163        # which are related to this dataset
164        current_plots = [name for name in shown_plot_names if PlotHelper.plotById(name).data.id in plot_ids]
165
166        for name in current_plots:
167            # get the plotter object first
168            plotter = PlotHelper.plotById(name)
169            graphs.append(plotter.figure)
170
171        return graphs
172
173
174# Simple html report template
175HEADER = "<html>\n"
176HEADER += "<head>\n"
177HEADER += "<meta http-equiv=Content-Type content='text/html; "
178HEADER += "charset=utf-8'> \n"
179HEADER += "<meta name=Generator >\n"
180HEADER += "</head>\n"
181HEADER += "<body lang=EN-US>\n"
182HEADER += "<div class=WordSection1>\n"
183HEADER += "<p class=MsoNormal><b><span ><center><font size='4' >"
184HEADER += "%s</font></center></span></center></b></p>"
185HEADER += "<p class=MsoNormal>&nbsp;</p>"
186PARA = "<p class=MsoNormal><font size='4' > %s \n"
187PARA += "</font></p>"
188CENTRE = "<p class=MsoNormal><center><font size='4' > %s \n"
189CENTRE += "</font></center></p>"
190FEET_1 = \
191"""
192<p class=MsoNormal>&nbsp;</p>
193<br>
194<p class=MsoNormal><b><span ><center> <font size='4' > Graph
195</font></span></center></b></p>
196<p class=MsoNormal>&nbsp;</p>
197<center>
198<br><font size='4' >Model Computation</font>
199<br><font size='4' >Data: "%s"</font><br>
200"""
201FEET_2 = \
202'''<img src="data:image/png;base64,{}"></img>
203'''
204FEET_3 = \
205'''<img width="540" src="data:image/png;base64,{}"></img>
206'''
207ELINE = """<p class=MsoNormal>&nbsp;</p>
208"""
209
Note: See TracBrowser for help on using the repository browser.