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
"""
import urllib
import json
import matplotlib
import re
from plugin_dbui import INLINE_ALERT
from report_objects import do_title, List, Metric1D, Metric2D
from selector import MySelector
from StringIO import StringIO
def graph():
"""Plot 2D metric as a C{Ext.char.series.Area}
def graph_extjs():
"""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
......@@ -19,32 +25,70 @@ def graph():
# homomorphism between metric2D and graph
config = db.graphs[request.vars.id_graphs]
config.field_vertical = config.field_horizontal
config.field_horizontal = config.field_stacked
config.group_field_y = config.field_horizontal
config.group_field_x = config.field_stacked
config.field_z = 'people.id'
config.metric = 'size'
config.metric_field_z = 'people.id'
config.aggregation_z = 'size'
# the metric might be superseded by the user
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.
# generate the metric according to user specification
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)
stack_keys = [el for el in report.df.columns]
# 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)
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():
"""Render the report through the C{App.grid.Panel}.
The report can be a list, a metrics 1d or 2d.
......
......@@ -145,7 +145,7 @@ graphNode = Node(T('The graphs'))
for row in db(db.graphs.id > 0).select(orderby=db.graphs.name):
leaf = PanelWithUrlSelector(virtdb.graph_selector,
baseUrl=URL('report', 'graph'),
baseUrl=URL('report', 'graph_mpl'),
baseParams={'id_graphs': row.id})
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