|
1 """basic plot views |
|
2 |
|
3 :organization: Logilab |
|
4 :copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL. |
|
5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
|
6 """ |
|
7 __docformat__ = "restructuredtext en" |
|
8 |
1 import os |
9 import os |
2 |
10 |
3 from logilab.common import flatten |
11 from logilab.common import flatten |
|
12 from logilab.mtconverter import html_escape |
4 |
13 |
5 from cubicweb.vregistry import objectify_selector |
14 from cubicweb.vregistry import objectify_selector |
6 from cubicweb.web.views import baseviews |
15 from cubicweb.web.views import baseviews |
7 |
16 |
8 @objectify_selector |
17 @objectify_selector |
9 def plot_selector(cls, req, rset, *args, **kwargs): |
18 def plot_selector(cls, req, rset, *args, **kwargs): |
10 """accept result set with at least one line and two columns of result |
19 """accept result set with at least one line and two columns of result |
11 all columns after second must be of numerical types""" |
20 all columns after second must be of numerical types""" |
12 if rset is None: |
21 if not rset: |
13 return 0 |
|
14 if not len(rset): |
|
15 return 0 |
22 return 0 |
16 if len(rset.rows[0]) < 2: |
23 if len(rset.rows[0]) < 2: |
17 return 0 |
24 return 0 |
18 for etype in rset.description[0]: |
25 for etype in rset.description[0]: |
19 if etype not in ('Int', 'Float'): |
26 if etype not in ('Int', 'Float'): |
20 return 0 |
27 return 0 |
|
28 return 1 |
|
29 |
|
30 @objectify_selector |
|
31 def piechart_selector(cls, req, rset, *args, **kwargs): |
|
32 if not rset: |
|
33 return 0 |
|
34 if len(rset.rows[0]) < 2: |
|
35 return 0 |
|
36 etype = rset.description[0][1] |
|
37 if etype not in ('Int', 'Float'): |
|
38 return 0 |
21 return 1 |
39 return 1 |
22 |
40 |
23 try: |
41 try: |
24 import matplotlib |
42 import matplotlib |
25 import sys |
43 import sys |
99 img.close() |
117 img.close() |
100 os.remove(filename) |
118 os.remove(filename) |
101 |
119 |
102 def build_figname(self): |
120 def build_figname(self): |
103 self.__class__._plot_count += 1 |
121 self.__class__._plot_count += 1 |
104 return '/tmp/burndown_chart_%s_%d.png' % (self.config.appid, self.__class__._plot_count) |
122 return '/tmp/burndown_chart_%s_%d.png' % (self.config.appid, |
|
123 self.__class__._plot_count) |
|
124 |
|
125 try: |
|
126 from GChartWrapper import Pie, Pie3D |
|
127 except ImportError: |
|
128 pass |
|
129 else: |
|
130 class PieChartView(baseviews.AnyRsetView): |
|
131 id = 'piechart' |
|
132 pieclass = Pie |
|
133 __select__ = piechart_selector() |
|
134 |
|
135 def call(self, title=None, width=None, height=None): |
|
136 piechart = self.pieclass([(row[1] or 0) for row in self.rset]) |
|
137 labels = ['%s: %s' % (row[0].encode(self.req.encoding), row[1]) |
|
138 for row in self.rset] |
|
139 piechart.label(*labels) |
|
140 if width is not None: |
|
141 height = height or width |
|
142 piechart.size(width, height) |
|
143 if title: |
|
144 piechart.title(title) |
|
145 self.w(u'<img src="%s" />' % html_escape(piechart.url)) |
|
146 |
|
147 |
|
148 class PieChart3DView(PieChartView): |
|
149 id = 'piechart3D' |
|
150 pieclass = Pie3D |