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

Last change on this file since d32a594 was 75906a1, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 6 years ago

More fixes from PK's CR

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