1# Copyright (c) 2005-2006 The Regents of The University of Michigan
2# All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are
6# met: redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer;
8# redistributions in binary form must reproduce the above copyright
9# notice, this list of conditions and the following disclaimer in the
10# documentation and/or other materials provided with the distribution;
11# neither the name of the copyright holders nor the names of its
12# contributors may be used to endorse or promote products derived from
13# this software without specific prior written permission.
14#
15# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26#
27# Authors: Nathan Binkert
28
29from chart import ChartOptions
30
31class StatOutput(ChartOptions):
32    def __init__(self, jobfile, info, stat=None):
33        super(StatOutput, self).__init__()
34        self.jobfile = jobfile
35        self.stat = stat
36        self.invert = False
37        self.info = info
38
39    def display(self, name, printmode = 'G'):
40        import info
41
42        if printmode == 'G':
43            valformat = '%g'
44        elif printmode != 'F' and value > 1e6:
45            valformat = '%0.5e'
46        else:
47            valformat = '%f'
48
49        for job in self.jobfile.jobs():
50            value = self.info.get(job, self.stat)
51            if value is None:
52                return
53
54            if not isinstance(value, list):
55                value = [ value ]
56
57            if self.invert:
58                for i,val in enumerate(value):
59                    if val != 0.0:
60                        value[i] = 1 / val
61
62            valstring = ', '.join([ valformat % val for val in value ])
63            print '%-50s    %s' % (job.name + ':', valstring)
64
65    def graph(self, name, graphdir, proxy=None):
66        from os.path import expanduser, isdir, join as joinpath
67        from barchart import BarChart
68        from matplotlib.numerix import Float, array, zeros
69        import os, re, urllib
70        from jobfile import crossproduct
71
72        confgroups = self.jobfile.groups()
73        ngroups = len(confgroups)
74        skiplist = [ False ] * ngroups
75        groupopts = []
76        baropts = []
77        groups = []
78        for i,group in enumerate(confgroups):
79            if group.flags.graph_group:
80                groupopts.append(group.subopts())
81                skiplist[i] = True
82            elif group.flags.graph_bars:
83                baropts.append(group.subopts())
84                skiplist[i] = True
85            else:
86                groups.append(group)
87
88        has_group = bool(groupopts)
89        if has_group:
90            groupopts = [ group for group in crossproduct(groupopts) ]
91        else:
92            groupopts = [ None ]
93
94        if baropts:
95            baropts = [ bar for bar in crossproduct(baropts) ]
96        else:
97            raise AttributeError, 'No group selected for graph bars'
98
99        directory = expanduser(graphdir)
100        if not isdir(directory):
101            os.mkdir(directory)
102        html = file(joinpath(directory, '%s.html' % name), 'w')
103        print >>html, '<html>'
104        print >>html, '<title>Graphs for %s</title>' % name
105        print >>html, '<body>'
106        html.flush()
107
108        for options in self.jobfile.options(groups):
109            chart = BarChart(self)
110
111            data = [ [ None ] * len(baropts) for i in xrange(len(groupopts)) ]
112            enabled = False
113            stacked = 0
114            for g,gopt in enumerate(groupopts):
115                for b,bopt in enumerate(baropts):
116                    if gopt is None:
117                        gopt = []
118                    job = self.jobfile.job(options + gopt + bopt)
119                    if not job:
120                        continue
121
122                    if proxy:
123                        import db
124                        proxy.dict['system'] = self.info[job.system]
125                    val = self.info.get(job, self.stat)
126                    if val is None:
127                        print 'stat "%s" for job "%s" not found' % \
128                              (self.stat, job)
129
130                    if isinstance(val, (list, tuple)):
131                        if len(val) == 1:
132                            val = val[0]
133                        else:
134                            stacked = len(val)
135
136                    data[g][b] = val
137
138            if stacked == 0:
139                for i in xrange(len(groupopts)):
140                    for j in xrange(len(baropts)):
141                        if data[i][j] is None:
142                            data[i][j] = 0.0
143            else:
144                for i in xrange(len(groupopts)):
145                    for j in xrange(len(baropts)):
146                        val = data[i][j]
147                        if val is None:
148                            data[i][j] = [ 0.0 ] * stacked
149                        elif len(val) != stacked:
150                            raise ValueError, "some stats stacked, some not"
151
152            data = array(data)
153            if data.sum() == 0:
154                continue
155
156            dim = len(data.shape)
157            x = data.shape[0]
158            xkeep = [ i for i in xrange(x) if data[i].sum() != 0 ]
159            y = data.shape[1]
160            ykeep = [ i for i in xrange(y) if data[:,i].sum() != 0 ]
161            data = data.take(xkeep, axis=0)
162            data = data.take(ykeep, axis=1)
163            if not has_group:
164                data = data.take([ 0 ], axis=0)
165            chart.data = data
166
167
168            bopts = [ baropts[i] for i in ykeep ]
169            bdescs = [ ' '.join([o.desc for o in opt]) for opt in bopts]
170
171            if has_group:
172                gopts = [ groupopts[i] for i in xkeep ]
173                gdescs = [ ' '.join([o.desc for o in opt]) for opt in gopts]
174
175            if chart.legend is None:
176                if stacked:
177                    try:
178                        chart.legend = self.info.rcategories
179                    except:
180                        chart.legend = [ str(i) for i in xrange(stacked) ]
181                else:
182                    chart.legend = bdescs
183
184            if chart.xticks is None:
185                if has_group:
186                    chart.xticks = gdescs
187                else:
188                    chart.xticks = []
189            chart.graph()
190
191            names = [ opt.name for opt in options ]
192            descs = [ opt.desc for opt in options ]
193
194            if names[0] == 'run':
195                names = names[1:]
196                descs = descs[1:]
197
198            basename = '%s-%s' % (name, ':'.join(names))
199            desc = ' '.join(descs)
200
201            pngname = '%s.png' % basename
202            psname = '%s.eps' % re.sub(':', '-', basename)
203            epsname = '%s.ps' % re.sub(':', '-', basename)
204            chart.savefig(joinpath(directory, pngname))
205            chart.savefig(joinpath(directory, epsname))
206            chart.savefig(joinpath(directory, psname))
207            html_name = urllib.quote(pngname)
208            print >>html, '''%s<br><img src="%s"><br>''' % (desc, html_name)
209            html.flush()
210
211        print >>html, '</body>'
212        print >>html, '</html>'
213        html.close()
214