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

Reply via email to