Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 90f7d50

Browse files
committed
add interactive svg histogram example.
1 parent 0d4a2e1 commit 90f7d50

1 file changed

Lines changed: 131 additions & 0 deletions

File tree

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#!/usr/bin/env python
2+
#-*-encoding:utf8-*-
3+
4+
"""
5+
Demonstrate how to create an interactive histogram, in which bars
6+
are hidden or shown by cliking on legend markers.
7+
8+
The interactivity is encoded in ecmascript and inserted in the SVG code
9+
in a post-processing step. To render the image, open it in a web
10+
browser. SVG is supported in most web browsers used by Linux and OSX
11+
users. Windows IE9 supports SVG, but earlier versions do not.
12+
13+
__author__="[email protected]"
14+
15+
"""
16+
17+
import numpy as np
18+
import matplotlib.pyplot as plt
19+
import xml.etree.ElementTree as ET
20+
from StringIO import StringIO
21+
22+
plt.rcParams['svg.embed_char_paths'] = 'none'
23+
24+
# Apparently, this `register_namespace` method works only with
25+
# python 2.7 and up and is necessary to avoid garbling the XML name
26+
# space with ns0.
27+
ET.register_namespace("","http://www.w3.org/2000/svg")
28+
29+
30+
def python2js(d):
31+
"""Return a string representation of a python dictionary in
32+
ecmascript object syntax."""
33+
34+
objs = []
35+
for key, value in d.items():
36+
objs.append( key + ':' + str(value) )
37+
38+
return '{' + ', '.join(objs) + '}'
39+
40+
41+
# --- Create histogram, legend and title ---
42+
plt.figure()
43+
r = np.random.randn(100)
44+
r1 = r + 1
45+
labels = ['Rabbits', 'Frogs']
46+
H = plt.hist([r,r1], label=labels)
47+
containers = H[-1]
48+
leg = plt.legend(frameon=False)
49+
plt.title("""From a web browser, click on the legend
50+
marker to toggle the corresponding histogram.""")
51+
52+
53+
# --- Add ids to the svg objects we'll modify
54+
55+
hist_patches = {}
56+
for ic, c in enumerate(containers):
57+
hist_patches['hist_%d'%ic] = []
58+
for il, element in enumerate(c):
59+
element.set_gid('hist_%d_patch_%d'%(ic, il))
60+
hist_patches['hist_%d'%ic].append('hist_%d_patch_%d'%(ic,il))
61+
62+
# Set ids for the legend patches
63+
for i, t in enumerate(leg.get_patches()):
64+
t.set_gid('leg_patch_%d'%i)
65+
66+
# Save SVG in a fake file object.
67+
f = StringIO()
68+
plt.savefig(f, format="svg")
69+
70+
# Create XML tree from the SVG file.
71+
tree, xmlid = ET.XMLID(f.getvalue())
72+
73+
74+
# --- Add interactivity ---
75+
76+
# Add attributes to the patch objects.
77+
for i, t in enumerate(leg.get_patches()):
78+
el = xmlid['leg_patch_%d'%i]
79+
el.set('cursor', 'pointer')
80+
el.set('opacity', '1.0')
81+
el.set('onclick', "toggle_element(evt, 'hist_%d')"%i)
82+
83+
# Create script defining the function `toggle_element`.
84+
# We create a global variable `container` that stores the patches id
85+
# belonging to each histogram. Then a function "toggle_element" sets the
86+
# visibility attribute of all patches of each histogram and the opacity
87+
# of the marker itself.
88+
89+
script = """
90+
<script type="text/ecmascript">
91+
<![CDATA[
92+
var container = %s
93+
94+
function toggle_element(evt, element) {
95+
96+
var names = container[element]
97+
var el, state;
98+
99+
state = evt.target.getAttribute("opacity") == 1.0 ||
100+
evt.target.getAttribute("opacity") == null;
101+
102+
if (state) {
103+
evt.target.setAttribute("opacity", 0.5);
104+
105+
for (var i=0; i < names.length; i++) {
106+
el = document.getElementById(names[i]);
107+
el.setAttribute("visibility","hidden");
108+
}
109+
}
110+
111+
else {
112+
evt.target.setAttribute("opacity", 1);
113+
114+
for (var i=0; i < names.length; i++) {
115+
el = document.getElementById(names[i]);
116+
el.setAttribute("visibility","visible");
117+
}
118+
119+
};
120+
};
121+
]]>
122+
</script>
123+
"""%python2js(hist_patches)
124+
125+
# Insert the script and save to file.
126+
tree.insert(0, ET.XML(script))
127+
128+
ET.ElementTree(tree).write("svg_histogram.svg")
129+
130+
131+

0 commit comments

Comments
 (0)