FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
matplotlib/examples/user_interfaces/svg_histogram.py at master · wrightrocket/matplotlib · GitHub
wrightrocket
matplotlib
Repository navigation
Code
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
matplotlib
/
examples
/
user_interfaces
/
svg_histogram.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
executable file
·
155 lines (118 loc) · 4.45 KB
Breadcrumbs
matplotlib
/
examples
/
user_interfaces
/
svg_histogram.py
Copy path
File metadata and controls
executable file
·
155 lines (118 loc) · 4.45 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/usr/bin/env python
#-*- encoding:utf-8 -*-
"""
Demonstrate how to create an interactive histogram, in which bars
are hidden or shown by cliking on legend markers.
The interactivity is encoded in ecmascript (javascript) and inserted in
the SVG code in a post-processing step. To render the image, open it in
a web browser. SVG is supported in most web browsers used by Linux and
OSX users. Windows IE9 supports SVG, but earlier versions do not.
Notes
-----
The matplotlib backend lets us assign ids to each object. This is the
mechanism used here to relate matplotlib objects created in python and
the corresponding SVG constructs that are parsed in the second step.
While flexible, ids are cumbersome to use for large collection of
objects. Two mechanisms could be used to simplify things:
* systematic grouping of objects into SVG <g> tags,
* assingning classes to each SVG object according to its origin.
For example, instead of modifying the properties of each individual bar,
the bars from the `hist` function could either be grouped in
a PatchCollection, or be assigned a class="hist_##" attribute.
CSS could also be used more extensively to replace repetitive markup
troughout the generated SVG.
__author__="david.huard@gmail.com"
"""
import
numpy
as
np
import
matplotlib
.
pyplot
as
plt
import
xml
.
etree
.
ElementTree
as
ET
from
StringIO
import
StringIO
import
json
plt
.
rcParams
[
'svg.embed_char_paths'
]
=
'none'
# Apparently, this `register_namespace` method works only with
# python 2.7 and up and is necessary to avoid garbling the XML name
# space with ns0.
ET
.
register_namespace
(
""
,
"http://www.w3.org/2000/svg"
)
# --- Create histogram, legend and title ---
plt
.
figure
()
r
=
np
.
random
.
randn
(
100
)
r1
=
r
+
1
labels
=
[
'Rabbits'
,
'Frogs'
]
H
=
plt
.
hist
([
r
,
r1
],
label
=
labels
)
containers
=
H
[
-
1
]
leg
=
plt
.
legend
(
frameon
=
False
)
plt
.
title
(
"From a web browser, click on the legend
\n
"
"marker to toggle the corresponding histogram."
)
# --- Add ids to the svg objects we'll modify
hist_patches
=
{}
for
ic
,
c
in
enumerate
(
containers
):
hist_patches
[
'hist_%d'
%
ic
]
=
[]
for
il
,
element
in
enumerate
(
c
):
element
.
set_gid
(
'hist_%d_patch_%d'
%
(
ic
,
il
))
hist_patches
[
'hist_%d'
%
ic
].
append
(
'hist_%d_patch_%d'
%
(
ic
,
il
))
# Set ids for the legend patches
for
i
,
t
in
enumerate
(
leg
.
get_patches
()):
t
.
set_gid
(
'leg_patch_%d'
%
i
)
# Set ids for the text patches
for
i
,
t
in
enumerate
(
leg
.
get_texts
()):
t
.
set_gid
(
'leg_text_%d'
%
i
)
# Save SVG in a fake file object.
f
=
StringIO
()
plt
.
savefig
(
f
,
format
=
"svg"
)
# Create XML tree from the SVG file.
tree
,
xmlid
=
ET
.
XMLID
(
f
.
getvalue
())
# --- Add interactivity ---
# Add attributes to the patch objects.
for
i
,
t
in
enumerate
(
leg
.
get_patches
()):
el
=
xmlid
[
'leg_patch_%d'
%
i
]
el
.
set
(
'cursor'
,
'pointer'
)
el
.
set
(
'onclick'
,
"toggle_hist(this)"
)
# Add attributes to the text objects.
for
i
,
t
in
enumerate
(
leg
.
get_texts
()):
el
=
xmlid
[
'leg_text_%d'
%
i
]
el
.
set
(
'cursor'
,
'pointer'
)
el
.
set
(
'onclick'
,
"toggle_hist(this)"
)
# Create script defining the function `toggle_hist`.
# We create a global variable `container` that stores the patches id
# belonging to each histogram. Then a function "toggle_element" sets the
# visibility attribute of all patches of each histogram and the opacity
# of the marker itself.
script
=
"""
<script type="text/ecmascript">
<![CDATA[
var container = %s
function toggle(oid, attribute, values) {
/* Toggle the style attribute of an object between two values.
Parameters
----------
oid : str
Object identifier.
attribute : str
Name of syle attribute.
values : [on state, off state]
The two values that are switched between.
*/
var obj = document.getElementById(oid);
var a = obj.style[attribute];
a = (a == values[0] || a == "") ? values[1] : values[0];
obj.style[attribute] = a;
}
function toggle_hist(obj) {
var num = obj.id.slice(-1);
toggle('leg_patch_' + num, 'opacity', [1, 0.3]);
toggle('leg_text_' + num, 'opacity', [1, 0.5]);
var names = container['hist_'+num]
for (var i=0; i < names.length; i++) {
toggle(names[i], 'opacity', [1,0])
};
}
]]>
</script>
"""
%
json
.
dumps
(
hist_patches
)
# Add a transition effect
css
=
tree
.
getchildren
()[
0
][
0
]
css
.
text
=
css
.
text
+
"g {-webkit-transition:opacity 0.4s ease-out;"
+
\
"-moz-transition:opacity 0.4s ease-out;}"
# Insert the script and save to file.
tree
.
insert
(
0
,
ET
.
XML
(
script
))
ET
.
ElementTree
(
tree
).
write
(
"svg_histogram.svg"
)
Back
|
FazBrowse Home
|
New Git URL