psoares
psoares

Reputation: 4883

how to create hyperlink in piechart

I want to do a pie chart in matplotlib.
This pie chart will be a representation of two variables: male and female.

That's easy to do :)

What I would like to do next, I'm not even sure if it's possible to do with matplotlib, I would like to make these two variables clickable so if I click on male, I would see another page with information about this, same thing with female.

Image map isn't a solution since this variables may change in the future.

Anyone has any idea how to do this? If it's possible with matplotlib or what program would you recommend.

Thank you!

Upvotes: 3

Views: 1815

Answers (2)

Joe Kington
Joe Kington

Reputation: 284712

While it's not really in a workably stable state yet, have a look at the html5 canvas backend for matplotlib. It looks interesting, anyway, and will probably be the best way to do this sort of thing (interactive webpage with a matplotlib plot) in the future.

In the meantime, as @Mark suggested, it's not too hard to dynamically generate an imagemap for the wedges of a pie plot.

Here's a rough example, that I'm sure you could adapt to whatever web framework you're using.

import matplotlib.pyplot as plt

def main():
    # Make an example pie plot
    fig = plt.figure()
    ax = fig.add_subplot(111)

    labels = ['Beans', 'Squash', 'Corn']
    wedges, plt_labels = ax.pie([20, 40, 60], labels=labels)
    ax.axis('equal')

    make_image_map(fig, wedges, labels, 'temp.html')

def make_image_map(fig, wedges, labels, html_filename):
    """Makes an example static html page with a image map of a pie chart.."""
    #-- Save the figure as an image and get image size ------------------------
    # Be sure to explictly set the dpi when saving the figure
    im_filename = 'temp.png'
    fig.savefig(im_filename, dpi=fig.dpi)

    # Get figure size...
    _, _, fig_width, fig_height = fig.bbox.bounds

    #-- Get the coordinates of each wedge as a string of x1,y2,x2,y2... -------
    coords = []
    for wedge in wedges:
        xy = wedge.get_verts() 

        # Transform to pixel coords
        xy = fig.get_transform().transform(xy) 

        # Format into coord string and convert to <0,0> in top left...
        xy = ', '.join(['%0.2f,%0.2f' % (x, fig_height - y) for x, y in xy])
        coords.append(xy)

    #-- Build web page --------------------------------------------------------
    header = """
    <html>
    <body>
    <img src="{0}" alt="Pie Chart" usemap="#pie_map" width="{1}" height="{2}" />
    """.format(im_filename, fig_width, fig_height)

    # Make the image map
    map = '<map name="pie_map">\n'
    for label, xy in zip(labels, coords):
        href = 'http://images.google.com/images?q={0}'.format(label)
        area = '<area shape="poly" coords="{0}" href="{1}" alt="{2}" />'
        area = area.format(xy, href, label)
        map += '    ' + area + '\n'
    map += '</map>\n'

    footer = """
    </body>
    </html>"""

    # Write to a file...
    with file(html_filename, 'w') as outfile:
        outfile.write(header + map + footer)

if __name__ == '__main__':
    main()

Edit: I just realized that you might not be referring to embedding the plot into a web page... (I assumed that you were from the "display another page" bit in your question.) If you want more of a desktop app, without having to mess with a "full" gui toolkit, you can do something like this:

import matplotlib.pyplot as plt

def main():
    # Make an example pie plot
    fig = plt.figure()
    ax = fig.add_subplot(111)

    labels = ['Beans', 'Squash', 'Corn']
    wedges, plt_labels = ax.pie([20, 40, 60], labels=labels)
    ax.axis('equal')

    make_picker(fig, wedges)
    plt.show()

def make_picker(fig, wedges):
    import webbrowser
    def on_pick(event):
        wedge = event.artist
        label = wedge.get_label()
        webbrowser.open('http://images.google.com/images?q={0}'.format(label))

    # Make wedges selectable
    for wedge in wedges:
        wedge.set_picker(True)

    fig.canvas.mpl_connect('pick_event', on_pick)

if __name__ == '__main__':
    main()

Which opens a browser window for a google image search of whatever the wedge is labeled as...

Upvotes: 5

Mark Snidovich
Mark Snidovich

Reputation: 1055

You can do this with an imagemap or HTML element overlay controlled by JavaScript/jQuery.

Essentially, send your chart data to the page along with the chart image, and use JS to create the elements with the links according to the specification of the data.

It's a bit harder than the bar graphs I've done this to before, but should work fine.

Upvotes: 1

Related Questions