Hi, I'm trying to create an SVG figure that will show or hide the bars of a histogram when clicking on the element in the legend. I got to the point where it almost works...
I'm including the script so that others can play with it, but from what I understand, the problem is that the first histogram patch definition includes a clipping path definition <defs> <clipPath id="p7ff5b81e1d"> <rect height="345.6" width="446.4" x="72.0" y="43.2" /> </clipPath> </defs> that is referenced by all other histogram patches. When setting the visibility attribute of the first patch to "hidden" , it hides all patches. If I remove this clipping path entirely (by hand), the interactive components work as expected. This is my first foray in SVG so my approach is probably naive, but I'd welcome suggestions to make this work. Having one clippath per histogram item would simplify things, but I don't know the internals of matplotlib well enough to do this elegantly. Thanks, David
#-*-encoding:utf8-*- import numpy as np import matplotlib.pyplot as plt import xml.etree.ElementTree as ET from StringIO import StringIO def svg_hist_toggle(): plt.figure() plt.rcParams['svg.embed_char_paths'] = 'none' # Create histogram and legend r = np.random.randn(100) r1 = r + 1 labels = ['rabbit', 'frog'] H = plt.hist([r,r1], label=labels) containers = H[-1] leg = plt.legend() # Set an individual id to each patch. 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 and labels for i, t in enumerate(leg.get_texts()): t.set_gid('leg_text_%d'%i) for i, t in enumerate(leg.get_patches()): t.set_gid('leg_patch_%d'%i) # Save SVG in string f = StringIO() plt.savefig(f, format="svg") # Modify the SVG to add interactivity # Apparently, this register_namespace method works only with python2.7 and up. ET.register_namespace("","http://www.w3.org/2000/svg") tree, xmlid = ET.XMLID(f.getvalue()) for i, t in enumerate(leg.get_texts()): el = xmlid['leg_text_%d'%i] el.set('cursor', 'pointer') el.set('onclick', "toggle_element('hist_%d')"%i) for i, t in enumerate(leg.get_patches()): xmlid['leg_patch_%d'%i].set('cursor', 'pointer') # We create a global variable that stores the patches id belonging # to each histogram. Then a function "toggle_element" sets the # visibility attribute of all patches of each histogram. script = """ <script type="text/ecmascript"> <![CDATA[ var container = %s function toggle_element(element) { var names = container[element] var el; for (var i=0; i < names.length; i++) { el = document.getElementById(names[i]); if (el.getAttribute('visibility') == 'hidden') el.setAttribute("visibility","visible"); else el.setAttribute("visibility","hidden"); }; } ]]> </script> """%python2js(hist_patches) # Insert the script at the top of the file tree.insert(0, ET.XML(script)) # Save the modified file. fn = "svg_hist.svg" ET.ElementTree(tree).write(fn) def python2js(d): """Return a string representation of an object in js from a python dictionary.""" objs = [] for key, value in d.items(): objs.append( key + ':' + str(value) ) return '{' + ', '.join(objs) + '}'
------------------------------------------------------------------------------ uberSVN's rich system and user administration capabilities and model configuration take the hassle out of deploying and managing Subversion and the tools developers use with it. Learn more about uberSVN and get a free download at: http://p.sf.net/sfu/wandisco-dev2dev
_______________________________________________ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel