Commit e9a7529b authored by LE GAC Renaud's avatar LE GAC Renaud
Browse files

Graph report use matplotlib instead of Ext JS.

parent b58a7cdc
""" Report controllers """ Report controllers
""" """
import urllib
import json import json
import matplotlib
import re import re
from plugin_dbui import INLINE_ALERT from plugin_dbui import INLINE_ALERT
from report_objects import do_title, List, Metric1D, Metric2D from report_objects import do_title, List, Metric1D, Metric2D
from selector import MySelector from selector import MySelector
from StringIO import StringIO
def graph(): def graph_extjs():
"""Plot 2D metric as a C{Ext.char.series.Area} """Plot 2D metric as a C{Ext.char.series.Area} using the ExtJS library.
This action is kept as a test bench of ExtJS chart classes.
@deprecated: use the more generic graph_mpl
""" """
ui_table = virtdb.graph_selector ui_table = virtdb.graph_selector
...@@ -19,32 +25,70 @@ def graph(): ...@@ -19,32 +25,70 @@ def graph():
# homomorphism between metric2D and graph # homomorphism between metric2D and graph
config = db.graphs[request.vars.id_graphs] config = db.graphs[request.vars.id_graphs]
config.field_vertical = config.field_horizontal config.group_field_y = config.field_horizontal
config.field_horizontal = config.field_stacked config.group_field_x = config.field_stacked
config.field_z = 'people.id' config.metric_field_z = 'people.id'
config.metric = 'size' config.aggregation_z = 'size'
# the metric might be superseded by the user # generate the metric according to user specification
if selector.metric:
cpnfig.metric = config.metric
if not config.metric:
return INLINE_ALERT % (T('Error'), T('Please select a metric!'))
# build report and extract the configurations for
# the Ext.data.Store and App.grid.Panel.
report = Metric2D(config, selector) report = Metric2D(config, selector)
store = report.to_store()
# extract the configurations for the Ext.data.Store
store = report.to_store()
# Extra the stack keys (value for metric.field_vertical) # Extra the stack keys (value for metric.field_vertical)
stack_keys = [el for el in report.df.columns] stack_keys = [el for el in report.df.columns]
# delegate the rendering of the graph to the view # delegate the rendering of the graph to the view
response.view = 'report/graph.html'
return dict(cfg_store=json.dumps(store), stack_keys=stack_keys, view=config) return dict(cfg_store=json.dumps(store), stack_keys=stack_keys, view=config)
def graph_mpl():
"""Plot list or metric using the matplotlib library
"""
ui_table = virtdb.graph_selector
selector = MySelector(ui_table, exclude_fields=('metric',))
# homomorphism between metric2D and graph
config = db.graphs[request.vars.id_graphs]
config.group_field_y = config.field_horizontal
config.group_field_x = config.field_stacked
config.metric_field_z = 'people.id'
config.aggregation_z = 'size'
# NOTE: the X11 back end is not needed on the server side. In addition
# Tkinter crash with the message "out of stack space" when the 2nd plot
# is generated.
# The documentation recommend to limit the matplotlib back end to Agg
# which is tuned to render high quality PNG image. But, it is also
# design to render PDF and SVG image without the X11 interface.
#
matplotlib.use('Agg')
# generate the plot according to user specification
report = Metric2D(config, selector)
df = report.to_df()
plot = df.plot(kind='bar', stacked=True)
# open a StingIO file
fi = StringIO()
# get the figure associated to the plot and save it in the file
fig = plot.get_figure()
fig.savefig(fi, format='svg')
fig.clear()
# recuperate the data and delegate the final rendering to the view
# encode the data for URI
data = fi.getvalue()
fi.close()
return dict(data=data)
def grid(): def grid():
"""Render the report through the C{App.grid.Panel}. """Render the report through the C{App.grid.Panel}.
The report can be a list, a metrics 1d or 2d. The report can be a list, a metrics 1d or 2d.
......
...@@ -145,7 +145,7 @@ graphNode = Node(T('The graphs')) ...@@ -145,7 +145,7 @@ graphNode = Node(T('The graphs'))
for row in db(db.graphs.id > 0).select(orderby=db.graphs.name): for row in db(db.graphs.id > 0).select(orderby=db.graphs.name):
leaf = PanelWithUrlSelector(virtdb.graph_selector, leaf = PanelWithUrlSelector(virtdb.graph_selector,
baseUrl=URL('report', 'graph'), baseUrl=URL('report', 'graph_mpl'),
baseParams={'id_graphs': row.id}) baseParams={'id_graphs': row.id})
graphNode.add_child(row.name, leaf) graphNode.add_child(row.name, leaf)
......
{{
#--------------------------------------------------------------------------
#
# The python controller return image as a string:
# - data (string)
#
#--------------------------------------------------------------------------
import urllib
#
data = urllib.quote(data)
}}
<img src="data:image/svg+xml;utf8,{{=data}}" height=400></img>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment