In [6]:
# option
"""
echarts.option
~~~~~~~~~~~~~~
Options for chart
"""
import json
class Base(object):
def __str__(self):
"""JSON stringify format data."""
return json.dumps(self.json)
def __getitem__(self, key):
return self.json.get(key)
def keys(self):
return self.json.keys()
@property
def json(self):
raise NotImplementedError
class Axis(Base):
"""Axis data structure."""
def __init__(self, type, position, name='', data=None, **kwargs):
assert type in ('category', 'value', 'time')
self.type = type
assert position in ('bottom', 'top', 'left', 'right')
self.position = position
self.name = name
self.data = data or []
self._kwargs = kwargs
def __repr__(self):
return 'Axis<%s/%s>' % (self.type, self.position)
@property
def json(self):
"""JSON format data."""
json = dict(
type=self.type,
position=self.position,
data=self.data
)
if self.name:
json['name'] = self.name
if self._kwargs:
json.update(self._kwargs)
return json
class Legend(Base):
"""Legend section for Echart."""
def __init__(self, data, orient='horizontal', position=None, **kwargs):
self.data = data
assert orient in ('horizontal', 'vertical')
self.orient = orient
if not position:
position = ('center', 'top')
self.position = position
self._kwargs = kwargs
@property
def json(self):
"""JSON format data."""
json = {
'data': self.data,
'orient': self.orient,
'x': self.position[0],
'y': self.position[1]
}
if self._kwargs:
json.update(self._kwargs)
return json
class Tooltip(Base):
"""A tooltip when hovering."""
def __init__(self, trigger='axis', **kwargs):
assert trigger in ('axis', 'item')
self.trigger = trigger
self._kwargs = kwargs
@property
def json(self):
"""JSON format data."""
json = {
'trigger': self.trigger,
}
if self._kwargs:
json.update(self._kwargs)
return json
class Series(Base):
""" Data series holding. """
def __init__(self, type, name=None, data=None, **kwargs):
types = (
'bar', 'boxplot', 'candlestick', 'chord', 'effectScatter',
'eventRiver', 'force', 'funnel', 'gauge', 'graph', 'heatmap',
'k', 'line', 'lines', 'map', 'parallel', 'pie', 'radar',
'sankey', 'scatter', 'tree', 'treemap', 'venn', 'wordCloud'
)
assert type in types
self.type = type
self.name = name
self.data = data or []
self._kwargs = kwargs
@property
def json(self):
"""JSON format data."""
json = {
'type': self.type,
'data': self.data
}
if self.name:
json['name'] = self.name
if self._kwargs:
json.update(self._kwargs)
return json
class Toolbox(Base):
""" A toolbox for visitor. """
def __init__(self, orient='horizontal', position=None, **kwargs):
assert orient in ('horizontal', 'vertical')
self.orient = orient
if not position:
position = ('right', 'top')
self.position = position
self._kwargs = kwargs
@property
def json(self):
"""JSON format data."""
json = {
'orient': self.orient,
'x': self.position[0],
'y': self.position[1]
}
if self._kwargs:
json.update(self._kwargs)
return json
class VisualMap(Base):
"""maps data to visual channels"""
def __init__(self, type, min, max, **kwargs):
assert type in ("continuous", "piecewise")
self.type = type
self.min = min
self.max = max
self._kwargs = kwargs
@property
def json(self):
"""JSON format data"""
json = {
"type": self.type,
'min': self.min,
'max': self.max
}
if self._kwargs:
json.update(self._kwargs)
return json
In [7]:
# data structure
"""
echarts.datastructure
~~~~~~~~~~~~~~~~~~~~~
Datastructure for describing the chart types.
"""
# from .option import Series
class Line(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Line, self).__init__('line', name=name, data=data, **kwargs)
class Bar(Series):
" Docs "
def __init__(self, name=None, data=None, **kwargs):
super(Bar, self).__init__('bar', name=name, data=data, **kwargs)
class Pie(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Pie, self).__init__('pie', name=name, data=data, **kwargs)
class Scatter(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Scatter, self).__init__(
'scatter', name=name, data=data, **kwargs
)
class EffectScatter(Series):
def __init__(self, name=None, data=None, **kwargs):
super(EffectScatter, self).__init__(
'effectScatter', name=name, data=data, **kwargs
)
class Radar(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Radar, self).__init__('radar', name=name, data=data, **kwargs)
class Treemap(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Treemap, self).__init__(
'treemap', name=name, data=data, **kwargs
)
class Boxplot(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Boxplot, self).__init__(
'boxplot', name=name, data=data, **kwargs
)
class Candlestick(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Candlestick, self).__init__(
'candlestick', name=name, data=data, **kwargs
)
class Heatmap(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Heatmap, self).__init__(
'heatmap', name=name, data=data, **kwargs
)
class Map(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Map, self).__init__('map', name=name, data=data, **kwargs)
class Parallel(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Parallel, self).__init__(
'parallel', name=name, data=data, **kwargs
)
class Lines(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Lines, self).__init__('lines', name=name, data=data, **kwargs)
class Graph(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Graph, self).__init__('graph', name=name, data=data, **kwargs)
class Sankey(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Sankey, self).__init__('sankey', name=name, data=data, **kwargs)
class Funnel(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Funnel, self).__init__('funnel', name=name, data=data, **kwargs)
class Gauge(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Gauge, self).__init__('gauge', name=name, data=data, **kwargs)
# The following chart types are only available in echarts 2 version.
class K(Series):
def __init__(self, name=None, data=None, **kwargs):
super(K, self).__init__('k', name=name, data=data, **kwargs)
class Force(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Force, self).__init__('force', name=name, data=data, **kwargs)
class Chord(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Chord, self).__init__('chord', name=name, data=data, **kwargs)
class Venn(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Venn, self).__init__('venn', name=name, data=data, **kwargs)
class Tree(Series):
def __init__(self, name=None, data=None, **kwargs):
super(Tree, self).__init__('tree', name=name, data=data, **kwargs)
class EventRiver(Series):
def __init__(self, name=None, data=None, **kwargs):
super(EventRiver, self).__init__(
'eventRiver', name=name, data=data, **kwargs
)
class WordCloud(Series):
def __init__(self, name=None, data=None, **kwargs):
super(WordCloud, self).__init__(
'wordCloud', name=name, data=data, **kwargs
)
VERSION_2 = (
Line, Bar, Scatter, K, Pie, Radar, Chord, Force, Map,
Gauge, Funnel, EventRiver, Venn, Treemap, Tree, WordCloud, Heatmap
)
VERSION_3 = (
Line, Bar, Pie, Scatter, EffectScatter, Radar, Treemap, Boxplot,
Candlestick, Heatmap, Map, Parallel, Lines, Graph, Sankey, Funnel, Gauge
)
VERSION_ALL = tuple(set(VERSION_2).union(set(VERSION_3)))
In [8]:
# -*- coding: utf-8 -*-
"""
echarts
~~~~~~~
An unofficial Echarts options generator with Python.
:copyright: (c) 2014 by Hsiaoming Yang <me@lepture.com>.
:license: MIT, see `MIT <https://opensource.org/licenses/MIT>`_ for more details.
"""
import os
import json
import logging
import tempfile
import webbrowser
__version__ = '0.1'
__release__ = '0.1.3'
__author__ = 'Hsiaoming Yang <me@lepture.com>'
class Echart(Base):
def __init__(self, title, description=None, axis=True, **kwargs):
self.title = {
'text': title,
'subtext': description,
}
self.axis = axis
if self.axis:
self.x_axis = []
self.y_axis = []
self.series = []
self.kwargs = kwargs
self.logger = logging.getLogger(__name__)
def use(self, obj):
if isinstance(obj, Axis):
if obj.position in ('bottom', 'top'):
self.x_axis.append(obj)
else:
self.y_axis.append(obj)
return self
if isinstance(obj, Legend):
self.legend = obj
elif isinstance(obj, Tooltip):
self.tooltip = obj
elif isinstance(obj, Series):
self.series.append(obj)
elif isinstance(obj, Toolbox):
self.toolbox = obj
elif isinstance(obj, VisualMap):
self.visualMap = obj
return self
@property
def data(self):
return self.series
@property
def json(self):
"""JSON format data."""
json = {
'title': self.title,
'series': list(map(dict, self.series)),
}
if self.axis:
json['xAxis'] = list(map(dict, self.x_axis)) or [{}]
json['yAxis'] = list(map(dict, self.y_axis)) or [{}]
if hasattr(self, 'legend'):
json['legend'] = self.legend.json
if hasattr(self, 'tooltip'):
json['tooltip'] = self.tooltip.json
if hasattr(self, 'toolbox'):
json['toolbox'] = self.toolbox.json
if hasattr(self, 'visualMap'):
json['visualMap'] = self.visualMap.json
json.update(self.kwargs)
return json
def _html(self):
with open(os.path.join(os.path.dirname(__file__), 'plot.j2')) as f:
template = f.read()
return template.replace('{{ opt }}', json.dumps(self.json, indent=4))
def plot(self, persist=True):
"""
Plot into html file
:param persist: persist output html to disk
"""
with tempfile.NamedTemporaryFile(suffix='.html', delete=not persist) as fobj:
fobj.write(self._html())
fobj.flush()
webbrowser.open('file://' + os.path.realpath(fobj.name))
persist or raw_input('Press enter for continue')
def save(self, path, name):
"""
Save html file into project dir
:param path: project dir
:param name: html file name
"""
if not os.path.exists(path):
os.makedirs(path)
with open(path+str(name)+".html", "w") as html_file:
html_file.write(self._html())
In [9]:
import os
__file__ = '/Users/chengjun/github/cjc/vis/echarts/'
os.path.dirname(__file__)
Out[9]:
In [10]:
help(Echart)
In [ ]:
In [12]:
chart = Echart(title = 'GDP', description = 'subtitle')
chart.use(Bar('China', [2, 3, 4, 5]))
chart.use(Legend(['GDP']))
chart.use(Axis('category', 'bottom', data=['Nov', 'Dec', 'Jan', 'Feb']))
Out[12]:
In [13]:
help(chart.use)
In [14]:
chart.plot()
In [31]:
chart.title
Out[31]:
In [ ]: