SVG clickable images

Hi,

I have a requirement to make clickable bar charts using the SVG output
(rather than html maps).

An initial look has suggested that the following changes would be required:

backend_bases.py: Add a url property to GraphicsContextBase
(defaulting to None, so it's all backwards compatible)
axes.py: Add a url option to the bar function and pass this on to the
constructor of the Rectangle object
patches.py: Pass the url option in the constructor for the Patch
object to the GraphicsContextBase object created in the draw function
backends/backend_svg.py: Add check to _draw_svg_element for url set in
gc. If it is, write out SVG code for xlink.

I can make these changes and (if people think it would be useful)
contribute the changes back. However, before I do this, I wanted to
check whether this is the right approach to take - I'm not experienced
with the internals of matplotlib and so if there's a better way of
doing it, I'd be grateful for the advice.

Once I got the bar charts working, I would be interested in possibly
extending this to other chart types.

Regards

Andrew

I think it is a good idea to add such a feature in mpl, and I guess it
would better to have some general way to provide backend specific
options.

Actually, I have been using a modified version of mpl which enables to
set the individual ID of the patches (this is only meaningful in case
of the svg backend) in a very similar way that Andrew described. The
purpose of setting ID is to do some postprocessing of the resulting
svg file. A small post about this can be found at

And my approach was also to use GCs. Although I don't quite like this
approach, it seems to be the easiest way because, as far as I know,
the backends in mpl does not know about the artists.

I think we may introduce a new dictionary property to the GC class and
also in the Artist. And modifies draw() methods of Patch and others so
that it use these properties to pass any optioanl information (
"url"or "id") to the backends.

But I'm not sure is if it is a good idea to expose this option (or
"url" in the Andrew's original post) to the functions in the axes.py.
We can just grab the return value of the "bar" command (which is a
list of patches) and set some backend specific options for each
patches.

Regards,

-JJ

···

On Wed, Oct 29, 2008 at 6:06 PM, Andrew Stock <matplotlib_dev@...663...> wrote:

Hi,

I have a requirement to make clickable bar charts using the SVG output
(rather than html maps).

An initial look has suggested that the following changes would be required:

backend_bases.py: Add a url property to GraphicsContextBase
(defaulting to None, so it's all backwards compatible)
axes.py: Add a url option to the bar function and pass this on to the
constructor of the Rectangle object
patches.py: Pass the url option in the constructor for the Patch
object to the GraphicsContextBase object created in the draw function
backends/backend_svg.py: Add check to _draw_svg_element for url set in
gc. If it is, write out SVG code for xlink.

I can make these changes and (if people think it would be useful)
contribute the changes back. However, before I do this, I wanted to
check whether this is the right approach to take - I'm not experienced
with the internals of matplotlib and so if there's a better way of
doing it, I'd be grateful for the advice.

Once I got the bar charts working, I would be interested in possibly
extending this to other chart types.

Regards

Andrew

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

Jae-Joon Lee wrote:

I think it is a good idea to add such a feature in mpl, and I guess it
would better to have some general way to provide backend specific
options.
  

Also note that this specific functionality isn't backend-specific. PDF files, for example, also have the ability to have clickable links. So any design we come up with should be seen as "general functionality which only some backends implement when the format supports it" rather than a "backend-specific hack". In this case, simply ignoring the url is a reasonable thing to do for backends that can't support it.

Actually, I have been using a modified version of mpl which enables to
set the individual ID of the patches (this is only meaningful in case
of the svg backend) in a very similar way that Andrew described. The
purpose of setting ID is to do some postprocessing of the resulting
svg file. A small post about this can be found at

A Little Bit of Python, A Little Bit of Astronomy: Applying Filter Effects on SVG files created using Matplotlib
  

This is a very cool example -- and presents another great feature to add in the future (filtering). Again, it's conceivable that future versions of PDF may have similar functionality, so we should think about generic ways to do it. But that's probably another discussion...

And my approach was also to use GCs. Although I don't quite like this
approach, it seems to be the easiest way because, as far as I know,
the backends in mpl does not know about the artists.
  

You're right, the high-level artists that are exposed to the end user of matplotlib are somewhat removed from the low-level graphics primitives that are passed to the backends, and that may be problematic. But adding this to the GC of an artist is the cleanest way I can think of to add these extra properties that need to be passed to the backends, as we wouldn't have to change the backend API.

Since the creation of the gc for each drawing call happens mainly in base classes (Patch, Text, Collection), there shouldn't be too many places to update to add these extra attributes to the gc. We could handle these new attributes in Artist.draw and have Patch.draw, Text.draw, Collection.draw etc. delegate to that to reduce code duplication.

I think we may introduce a new dictionary property to the GC class and
also in the Artist. And modifies draw() methods of Patch and others so
that it use these properties to pass any optioanl information (
"url"or "id") to the backends.
  

Are you suggesting an extra dictionary in the gc to which arbitrary key/value pairs can be added? I don't like that very much. I think if we're going to support hyperlinks, we should create a true API for them that could be used across all backends (even if most backends can't support the functionality).

But I'm not sure is if it is a good idea to expose this option (or
"url" in the Andrew's original post) to the functions in the axes.py.
We can just grab the return value of the "bar" command (which is a
list of patches) and set some backend specific options for each
patches.
  

For the same reasons above, I don't see this as backend-specific, so I don't have a problem adding it as an Artist setter/kwarg that would be available on any method where Artist kwargs are supported. (And probably analogously have a list of urls for Collections).

In the specific case of bar(), one may still be forced to manually set urls on each Rectangle if one wants those urls to be different. But this is no different than the current situation wrt facecolor or any other attribute, since bar is not written on top of Collection.

Anyway, I like where this is going. I think this will be a great addition.

Cheers,
Mike

···

On Wed, Oct 29, 2008 at 6:06 PM, Andrew Stock > <matplotlib_dev@...663...> wrote:
  

Hi,

I have a requirement to make clickable bar charts using the SVG output
(rather than html maps).

An initial look has suggested that the following changes would be required:

backend_bases.py: Add a url property to GraphicsContextBase
(defaulting to None, so it's all backwards compatible)
axes.py: Add a url option to the bar function and pass this on to the
constructor of the Rectangle object
patches.py: Pass the url option in the constructor for the Patch
object to the GraphicsContextBase object created in the draw function
backends/backend_svg.py: Add check to _draw_svg_element for url set in
gc. If it is, write out SVG code for xlink.

I can make these changes and (if people think it would be useful)
contribute the changes back. However, before I do this, I wanted to
check whether this is the right approach to take - I'm not experienced
with the internals of matplotlib and so if there's a better way of
doing it, I'd be grateful for the advice.

Once I got the bar charts working, I would be interested in possibly
extending this to other chart types.

Regards

Andrew

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options
  
--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

better yet would be to replace the list of rectangles with a patch
collection, do the same for pie, etc. Then a single URL on the
collection would apply to the batch. This would break a fair amount
of code, but we might be able to minimize the pain by providing an
iter interface and a getitem interface to the collection, which warns
and does the right thing. So users who did

# bars was a list of Rectangles, now it is a PatchCollection
for bar in bars:
    bar.set_facecolor('red')

would get working code and a warning telling them to just do
bars.set_facecolors instead.

And, yes, the example is *very cool*

JDH

···

On Thu, Oct 30, 2008 at 8:10 AM, Michael Droettboom <mdroe@...31...> wrote:

In the specific case of bar(), one may still be forced to manually set
urls on each Rectangle if one wants those urls to be different. But
this is no different than the current situation wrt facecolor or any
other attribute, since bar is not written on top of Collection.

Another use case in favor of implementation of the URL property at the
artist level:

Consider a map with scatter points representing geolocated photos that
can be viewed at some URL. Attach a mouse click on the artist to the
following code:
import webbrowser
webbrowser.open(patch.url)
And you have an interactive map that lets you grab remote data.

-Eric

···

On Thu, Oct 30, 2008 at 10:02 AM, John Hunter <jdh2358@...149...> wrote:

On Thu, Oct 30, 2008 at 8:10 AM, Michael Droettboom <mdroe@...31...> wrote:

In the specific case of bar(), one may still be forced to manually set
urls on each Rectangle if one wants those urls to be different. But
this is no different than the current situation wrt facecolor or any
other attribute, since bar is not written on top of Collection.

better yet would be to replace the list of rectangles with a patch
collection, do the same for pie, etc. Then a single URL on the
collection would apply to the batch. This would break a fair amount
of code, but we might be able to minimize the pain by providing an
iter interface and a getitem interface to the collection, which warns
and does the right thing. So users who did

# bars was a list of Rectangles, now it is a PatchCollection
for bar in bars:
   bar.set_facecolor('red')

would get working code and a warning telling them to just do
bars.set_facecolors instead.

And, yes, the example is *very cool*

JDH

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

I realised in my earlier message, I didn't really address your initial request for feedback on your approach.

I think the goal here should be to make the url support as pervasive as possible wrt both plot types and backends.

Many of the high-level plotting functions (such as bar()) take a standard set of "Artist" keywords. In the docs, you'll often see a table like the one at the bottom for bar():

   http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.bar

This support all happens automatically simply by adding a setter and getter to the "Artist" class. So, in Artist, simply add set_url/get_url methods and a private attribute to store the url. You shouldn't have to touch any of the high-level plotting functions to have this supported everywhere where it makes sense.

Then, to use the url value, you'll want to store it in a GraphicsContext object to pass to the backend. So you'll want to add an attribute and getter/setter in GraphicsContextBase as well.

All of the places where the front-end creates a gc and passes it to the backend will need to be updated (such as Artist.draw, Text.draw, perhaps others, do a grep for the public methods in RendererBase). Where it sets things like facecolor on the GraphicsContext, it should also set a url.

Then, in backends where appropriate you would use the url value if present. You could start with SVG, and maybe someone can come along and add PDF support later.

An additional complication for completeness is handling Collections. Collections store a list of graphics context information (facecolor, edgecolor etc.) rather than a single one. Therefore, you'll want to add set_urls/get_urls to Collection as well, and then deal with passing those values to the backend. Collections don't use a GraphicsContext class, so you'll need to add a new arg to draw_path_collection in all backends. (Refactoring this so we pass an object to the backends rather than a long list of arguments would be welcome to avoid needing to update multiple backends for these sorts of new features in the future). You will also need to update RendererBase._iter_collection to support iterating over URLs in the same way as everything else there.

draw_image also doesn't use a gc, so you'll need to add an argument there.

Hope that gives you a road map... Please let me know if I can help further.

Mike

Andrew Stock wrote:

···

Hi,

I have a requirement to make clickable bar charts using the SVG output
(rather than html maps).

An initial look has suggested that the following changes would be required:

backend_bases.py: Add a url property to GraphicsContextBase
(defaulting to None, so it's all backwards compatible)
axes.py: Add a url option to the bar function and pass this on to the
constructor of the Rectangle object
patches.py: Pass the url option in the constructor for the Patch
object to the GraphicsContextBase object created in the draw function
backends/backend_svg.py: Add check to _draw_svg_element for url set in
gc. If it is, write out SVG code for xlink.

I can make these changes and (if people think it would be useful)
contribute the changes back. However, before I do this, I wanted to
check whether this is the right approach to take - I'm not experienced
with the internals of matplotlib and so if there's a better way of
doing it, I'd be grateful for the advice.

Once I got the bar charts working, I would be interested in possibly
extending this to other chart types.

Regards

Andrew

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options
  
--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

Hi,

I've attached a diff file which implements the basic functionality. It
currently doesn't handle collections or draw_image, but I wanted to
get something simple working first, before expanding the scope. A
simple test program is as follows:

from pylab import *

f = figure()
a,b = bar([1,2], [2,5], url='http://www.bbc.co.uk/')

a.set_url('http://www.google.com')

f.canvas.print_figure(r'c:\test.svg')

I'd be interested in comments / feedback on the attached before I
start to branch out into more significant changes!

Thanks

Andrew

svg_click.diff (4.15 KB)

···

On Thu, Oct 30, 2008 at 8:02 PM, Michael Droettboom <mdroe@...31...> wrote:

I realised in my earlier message, I didn't really address your initial
request for feedback on your approach.

I think the goal here should be to make the url support as pervasive as
possible wrt both plot types and backends.

Many of the high-level plotting functions (such as bar()) take a standard
set of "Artist" keywords. In the docs, you'll often see a table like the
one at the bottom for bar():

http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.bar

This support all happens automatically simply by adding a setter and getter
to the "Artist" class. So, in Artist, simply add set_url/get_url methods
and a private attribute to store the url. You shouldn't have to touch any
of the high-level plotting functions to have this supported everywhere where
it makes sense.

Then, to use the url value, you'll want to store it in a GraphicsContext
object to pass to the backend. So you'll want to add an attribute and
getter/setter in GraphicsContextBase as well.

All of the places where the front-end creates a gc and passes it to the
backend will need to be updated (such as Artist.draw, Text.draw, perhaps
others, do a grep for the public methods in RendererBase). Where it sets
things like facecolor on the GraphicsContext, it should also set a url.

Then, in backends where appropriate you would use the url value if present.
You could start with SVG, and maybe someone can come along and add PDF
support later.

An additional complication for completeness is handling Collections.
Collections store a list of graphics context information (facecolor,
edgecolor etc.) rather than a single one. Therefore, you'll want to add
set_urls/get_urls to Collection as well, and then deal with passing those
values to the backend. Collections don't use a GraphicsContext class, so
you'll need to add a new arg to draw_path_collection in all backends.
(Refactoring this so we pass an object to the backends rather than a long
list of arguments would be welcome to avoid needing to update multiple
backends for these sorts of new features in the future). You will also need
to update RendererBase._iter_collection to support iterating over URLs in
the same way as everything else there.

draw_image also doesn't use a gc, so you'll need to add an argument there.

Hope that gives you a road map... Please let me know if I can help further.

Mike

Andrew Stock wrote:

Hi,

I have a requirement to make clickable bar charts using the SVG output
(rather than html maps).

An initial look has suggested that the following changes would be
required:

backend_bases.py: Add a url property to GraphicsContextBase
(defaulting to None, so it's all backwards compatible)
axes.py: Add a url option to the bar function and pass this on to the
constructor of the Rectangle object
patches.py: Pass the url option in the constructor for the Patch
object to the GraphicsContextBase object created in the draw function
backends/backend_svg.py: Add check to _draw_svg_element for url set in
gc. If it is, write out SVG code for xlink.

I can make these changes and (if people think it would be useful)
contribute the changes back. However, before I do this, I wanted to
check whether this is the right approach to take - I'm not experienced
with the internals of matplotlib and so if there's a better way of
doing it, I'd be grateful for the advice.

Once I got the bar charts working, I would be interested in possibly
extending this to other chart types.

Regards

Andrew

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's
challenge
Build the coolest Linux based applications with Moblin SDK & win great
prizes
Grand prize is a trip for two to an Open Source event anywhere in the
world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

This looks great to me. I can confirm that this works on Linux as well.

I think from here it's just a matter of applying the same pattern of changes to collections and images. Once that's done, I'm happy to apply the patch. And if you plan to make a lot of changes in the future, it generally pretty easy to get commit access. Just ask.

Mike

Andrew Stock wrote:

···

Hi,

I've attached a diff file which implements the basic functionality. It
currently doesn't handle collections or draw_image, but I wanted to
get something simple working first, before expanding the scope. A
simple test program is as follows:

from pylab import *

f = figure()
a,b = bar([1,2], [2,5], url='http://www.bbc.co.uk/')

a.set_url('http://www.google.com')

f.canvas.print_figure(r'c:\test.svg')

I'd be interested in comments / feedback on the attached before I
start to branch out into more significant changes!

Thanks

Andrew

On Thu, Oct 30, 2008 at 8:02 PM, Michael Droettboom <mdroe@...31...> wrote:
  

I realised in my earlier message, I didn't really address your initial
request for feedback on your approach.

I think the goal here should be to make the url support as pervasive as
possible wrt both plot types and backends.

Many of the high-level plotting functions (such as bar()) take a standard
set of "Artist" keywords. In the docs, you'll often see a table like the
one at the bottom for bar():

http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.bar

This support all happens automatically simply by adding a setter and getter
to the "Artist" class. So, in Artist, simply add set_url/get_url methods
and a private attribute to store the url. You shouldn't have to touch any
of the high-level plotting functions to have this supported everywhere where
it makes sense.

Then, to use the url value, you'll want to store it in a GraphicsContext
object to pass to the backend. So you'll want to add an attribute and
getter/setter in GraphicsContextBase as well.

All of the places where the front-end creates a gc and passes it to the
backend will need to be updated (such as Artist.draw, Text.draw, perhaps
others, do a grep for the public methods in RendererBase). Where it sets
things like facecolor on the GraphicsContext, it should also set a url.

Then, in backends where appropriate you would use the url value if present.
You could start with SVG, and maybe someone can come along and add PDF
support later.

An additional complication for completeness is handling Collections.
Collections store a list of graphics context information (facecolor,
edgecolor etc.) rather than a single one. Therefore, you'll want to add
set_urls/get_urls to Collection as well, and then deal with passing those
values to the backend. Collections don't use a GraphicsContext class, so
you'll need to add a new arg to draw_path_collection in all backends.
(Refactoring this so we pass an object to the backends rather than a long
list of arguments would be welcome to avoid needing to update multiple
backends for these sorts of new features in the future). You will also need
to update RendererBase._iter_collection to support iterating over URLs in
the same way as everything else there.

draw_image also doesn't use a gc, so you'll need to add an argument there.

Hope that gives you a road map... Please let me know if I can help further.

Mike

Andrew Stock wrote:
    

Hi,

I have a requirement to make clickable bar charts using the SVG output
(rather than html maps).

An initial look has suggested that the following changes would be
required:

backend_bases.py: Add a url property to GraphicsContextBase
(defaulting to None, so it's all backwards compatible)
axes.py: Add a url option to the bar function and pass this on to the
constructor of the Rectangle object
patches.py: Pass the url option in the constructor for the Patch
object to the GraphicsContextBase object created in the draw function
backends/backend_svg.py: Add check to _draw_svg_element for url set in
gc. If it is, write out SVG code for xlink.

I can make these changes and (if people think it would be useful)
contribute the changes back. However, before I do this, I wanted to
check whether this is the right approach to take - I'm not experienced
with the internals of matplotlib and so if there's a better way of
doing it, I'd be grateful for the advice.

Once I got the bar charts working, I would be interested in possibly
extending this to other chart types.

Regards

Andrew

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's
challenge
Build the coolest Linux based applications with Moblin SDK & win great
prizes
Grand prize is a trip for two to an Open Source event anywhere in the
world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

Thanks Michael,

I've attached a new diff file which I believe also has all the
necessary changes to the collections and images. I've also attached
two simple scripts which test the collections and image functionality.

I've had to make some modification to extension code in this patch
which is definitely not my area of expertise so it would be worth
someone more experienced casting an eye over this.

I've tested this on Linux and successfully run the backend_driver.py
file (or at least, it failed with the same errors as before I applied
the patch!).

Any other comments welcome

Thanks

clickable.diff (20.7 KB)

image_show.py (567 Bytes)

scatter_test.py (182 Bytes)

···

On Wed, Nov 5, 2008 at 2:31 PM, Michael Droettboom <mdroe@...31...> wrote:

This looks great to me. I can confirm that this works on Linux as well.

I think from here it's just a matter of applying the same pattern of changes
to collections and images. Once that's done, I'm happy to apply the patch.
And if you plan to make a lot of changes in the future, it generally pretty
easy to get commit access. Just ask.

Mike

Andrew Stock wrote:

Hi,

I've attached a diff file which implements the basic functionality. It
currently doesn't handle collections or draw_image, but I wanted to
get something simple working first, before expanding the scope. A
simple test program is as follows:

from pylab import *

f = figure()
a,b = bar([1,2], [2,5], url='http://www.bbc.co.uk/')

a.set_url('http://www.google.com')

f.canvas.print_figure(r'c:\test.svg')

I'd be interested in comments / feedback on the attached before I
start to branch out into more significant changes!

Thanks

Andrew

On Thu, Oct 30, 2008 at 8:02 PM, Michael Droettboom <mdroe@...31...> >> wrote:

I realised in my earlier message, I didn't really address your initial
request for feedback on your approach.

I think the goal here should be to make the url support as pervasive as
possible wrt both plot types and backends.

Many of the high-level plotting functions (such as bar()) take a standard
set of "Artist" keywords. In the docs, you'll often see a table like the
one at the bottom for bar():

http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.bar

This support all happens automatically simply by adding a setter and
getter
to the "Artist" class. So, in Artist, simply add set_url/get_url methods
and a private attribute to store the url. You shouldn't have to touch
any
of the high-level plotting functions to have this supported everywhere
where
it makes sense.

Then, to use the url value, you'll want to store it in a GraphicsContext
object to pass to the backend. So you'll want to add an attribute and
getter/setter in GraphicsContextBase as well.

All of the places where the front-end creates a gc and passes it to the
backend will need to be updated (such as Artist.draw, Text.draw, perhaps
others, do a grep for the public methods in RendererBase). Where it sets
things like facecolor on the GraphicsContext, it should also set a url.

Then, in backends where appropriate you would use the url value if
present.
You could start with SVG, and maybe someone can come along and add PDF
support later.

An additional complication for completeness is handling Collections.
Collections store a list of graphics context information (facecolor,
edgecolor etc.) rather than a single one. Therefore, you'll want to add
set_urls/get_urls to Collection as well, and then deal with passing those
values to the backend. Collections don't use a GraphicsContext class, so
you'll need to add a new arg to draw_path_collection in all backends.
(Refactoring this so we pass an object to the backends rather than a
long
list of arguments would be welcome to avoid needing to update multiple
backends for these sorts of new features in the future). You will also
need
to update RendererBase._iter_collection to support iterating over URLs in
the same way as everything else there.

draw_image also doesn't use a gc, so you'll need to add an argument
there.

Hope that gives you a road map... Please let me know if I can help
further.

Mike

Andrew Stock wrote:

Hi,

I have a requirement to make clickable bar charts using the SVG output
(rather than html maps).

An initial look has suggested that the following changes would be
required:

backend_bases.py: Add a url property to GraphicsContextBase
(defaulting to None, so it's all backwards compatible)
axes.py: Add a url option to the bar function and pass this on to the
constructor of the Rectangle object
patches.py: Pass the url option in the constructor for the Patch
object to the GraphicsContextBase object created in the draw function
backends/backend_svg.py: Add check to _draw_svg_element for url set in
gc. If it is, write out SVG code for xlink.

I can make these changes and (if people think it would be useful)
contribute the changes back. However, before I do this, I wanted to
check whether this is the right approach to take - I'm not experienced
with the internals of matplotlib and so if there's a better way of
doing it, I'd be grateful for the advice.

Once I got the bar charts working, I would be interested in possibly
extending this to other chart types.

Regards

Andrew

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's
challenge
Build the coolest Linux based applications with Moblin SDK & win great
prizes
Grand prize is a trip for two to an Open Source event anywhere in the
world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

Andrew,

I just had a quick look at your patch.
I'm a bit distracted with your changes regarding the "url" support of the image.
Do we need to change the api of the draw_image()? Can we just utilize
"im" object as we did with the "gc"? Check the patch below. This
simple method seem to work fine for me.

I also noted that, in the __init__() methods of the Patch and the
AxesImage class, you explicitly declare "url" as a keyword argument
and also initialize self.url. I don't think these are necessary as
"url" is already a property of the Artist class.

IHTH,

-JJ

Index: lib/matplotlib/image.py

···

===================================================================
--- lib/matplotlib/image.py (revision 6361)
+++ lib/matplotlib/image.py (working copy)
@@ -234,6 +234,7 @@
             self.axes.get_yscale() != 'linear'):
             warnings.warn("Images are not supported on non-linear axes.")
         im = self.make_image(renderer.get_image_magnification())
+ im._url = self.get_url()
         l, b, widthDisplay, heightDisplay = self.axes.bbox.bounds
         renderer.draw_image(round(l), round(b), im, self.axes.bbox.frozen(),
                             *self.get_transformed_clip_path_and_affine())
Index: lib/matplotlib/backends/backend_svg.py

--- lib/matplotlib/backends/backend_svg.py (revision 6361)
+++ lib/matplotlib/backends/backend_svg.py (working copy)
@@ -274,6 +283,9 @@

         h,w = im.get_size_out()

+ url = im._url
+ if url is not None:
+ self._svgwriter.write('<a xlink:href="%s">' % url)
         self._svgwriter.write (
             '<image x="%f" y="%f" width="%f" height="%f" '
             '%s xlink:href="'%(x/trans[0],
(self.height-y)/trans[3]-h, w, h, transstr)
@@ -298,6 +310,8 @@
             self._svgwriter.write(filename)

         self._svgwriter.write('"/>\n')
+ if url is not None:
+ self._svgwriter.write('</a>')

     def draw_text(self, gc, x, y, s, prop, angle, ismath):
         if ismath:

On Thu, Nov 6, 2008 at 11:40 AM, Andrew Stock <matplotlib_dev@...663...> wrote:

Thanks Michael,

I've attached a new diff file which I believe also has all the
necessary changes to the collections and images. I've also attached
two simple scripts which test the collections and image functionality.

I've had to make some modification to extension code in this patch
which is definitely not my area of expertise so it would be worth
someone more experienced casting an eye over this.

I've tested this on Linux and successfully run the backend_driver.py
file (or at least, it failed with the same errors as before I applied
the patch!).

Any other comments welcome

Thanks

On Wed, Nov 5, 2008 at 2:31 PM, Michael Droettboom <mdroe@...31...> wrote:

This looks great to me. I can confirm that this works on Linux as well.

I think from here it's just a matter of applying the same pattern of changes
to collections and images. Once that's done, I'm happy to apply the patch.
And if you plan to make a lot of changes in the future, it generally pretty
easy to get commit access. Just ask.

Mike

Andrew Stock wrote:

Hi,

I've attached a diff file which implements the basic functionality. It
currently doesn't handle collections or draw_image, but I wanted to
get something simple working first, before expanding the scope. A
simple test program is as follows:

from pylab import *

f = figure()
a,b = bar([1,2], [2,5], url='http://www.bbc.co.uk/')

a.set_url('http://www.google.com')

f.canvas.print_figure(r'c:\test.svg')

I'd be interested in comments / feedback on the attached before I
start to branch out into more significant changes!

Thanks

Andrew

On Thu, Oct 30, 2008 at 8:02 PM, Michael Droettboom <mdroe@...31...> >>> wrote:

I realised in my earlier message, I didn't really address your initial
request for feedback on your approach.

I think the goal here should be to make the url support as pervasive as
possible wrt both plot types and backends.

Many of the high-level plotting functions (such as bar()) take a standard
set of "Artist" keywords. In the docs, you'll often see a table like the
one at the bottom for bar():

http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.bar

This support all happens automatically simply by adding a setter and
getter
to the "Artist" class. So, in Artist, simply add set_url/get_url methods
and a private attribute to store the url. You shouldn't have to touch
any
of the high-level plotting functions to have this supported everywhere
where
it makes sense.

Then, to use the url value, you'll want to store it in a GraphicsContext
object to pass to the backend. So you'll want to add an attribute and
getter/setter in GraphicsContextBase as well.

All of the places where the front-end creates a gc and passes it to the
backend will need to be updated (such as Artist.draw, Text.draw, perhaps
others, do a grep for the public methods in RendererBase). Where it sets
things like facecolor on the GraphicsContext, it should also set a url.

Then, in backends where appropriate you would use the url value if
present.
You could start with SVG, and maybe someone can come along and add PDF
support later.

An additional complication for completeness is handling Collections.
Collections store a list of graphics context information (facecolor,
edgecolor etc.) rather than a single one. Therefore, you'll want to add
set_urls/get_urls to Collection as well, and then deal with passing those
values to the backend. Collections don't use a GraphicsContext class, so
you'll need to add a new arg to draw_path_collection in all backends.
(Refactoring this so we pass an object to the backends rather than a
long
list of arguments would be welcome to avoid needing to update multiple
backends for these sorts of new features in the future). You will also
need
to update RendererBase._iter_collection to support iterating over URLs in
the same way as everything else there.

draw_image also doesn't use a gc, so you'll need to add an argument
there.

Hope that gives you a road map... Please let me know if I can help
further.

Mike

Andrew Stock wrote:

Hi,

I have a requirement to make clickable bar charts using the SVG output
(rather than html maps).

An initial look has suggested that the following changes would be
required:

backend_bases.py: Add a url property to GraphicsContextBase
(defaulting to None, so it's all backwards compatible)
axes.py: Add a url option to the bar function and pass this on to the
constructor of the Rectangle object
patches.py: Pass the url option in the constructor for the Patch
object to the GraphicsContextBase object created in the draw function
backends/backend_svg.py: Add check to _draw_svg_element for url set in
gc. If it is, write out SVG code for xlink.

I can make these changes and (if people think it would be useful)
contribute the changes back. However, before I do this, I wanted to
check whether this is the right approach to take - I'm not experienced
with the internals of matplotlib and so if there's a better way of
doing it, I'd be grateful for the advice.

Once I got the bar charts working, I would be interested in possibly
extending this to other chart types.

Regards

Andrew

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's
challenge
Build the coolest Linux based applications with Moblin SDK & win great
prizes
Grand prize is a trip for two to an Open Source event anywhere in the
world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

Jae-Joon,

Thanks for your comments. You have successfully found areas in my
patch that were overcomplicated!

I have attached a new patch which doesn't alter the api of draw_image
and uses the im object as Jae-Joon suggests.

I've tested this on Linux Python 2.5 as before, but not on Windows as
I don't have the correct development environment set up at the moment.

Regards

Andrew

clickable2.diff (15 KB)

···

On Fri, Nov 7, 2008 at 10:36 AM, Jae-Joon Lee <lee.j.joon@...149...> wrote:

Andrew,

I just had a quick look at your patch.
I'm a bit distracted with your changes regarding the "url" support of the image.
Do we need to change the api of the draw_image()? Can we just utilize
"im" object as we did with the "gc"? Check the patch below. This
simple method seem to work fine for me.

I also noted that, in the __init__() methods of the Patch and the
AxesImage class, you explicitly declare "url" as a keyword argument
and also initialize self.url. I don't think these are necessary as
"url" is already a property of the Artist class.

IHTH,

-JJ

Index: lib/matplotlib/image.py

--- lib/matplotlib/image.py (revision 6361)
+++ lib/matplotlib/image.py (working copy)
@@ -234,6 +234,7 @@
            self.axes.get_yscale() != 'linear'):
            warnings.warn("Images are not supported on non-linear axes.")
        im = self.make_image(renderer.get_image_magnification())
+ im._url = self.get_url()
        l, b, widthDisplay, heightDisplay = self.axes.bbox.bounds
        renderer.draw_image(round(l), round(b), im, self.axes.bbox.frozen(),
                            *self.get_transformed_clip_path_and_affine())
Index: lib/matplotlib/backends/backend_svg.py

--- lib/matplotlib/backends/backend_svg.py (revision 6361)
+++ lib/matplotlib/backends/backend_svg.py (working copy)
@@ -274,6 +283,9 @@

        h,w = im.get_size_out()

+ url = im._url
+ if url is not None:
+ self._svgwriter.write('<a xlink:href="%s">' % url)
        self._svgwriter.write (
            '<image x="%f" y="%f" width="%f" height="%f" '
            '%s xlink:href="'%(x/trans[0],
(self.height-y)/trans[3]-h, w, h, transstr)
@@ -298,6 +310,8 @@
            self._svgwriter.write(filename)

        self._svgwriter.write('"/>\n')
+ if url is not None:
+ self._svgwriter.write('</a>')

    def draw_text(self, gc, x, y, s, prop, angle, ismath):
        if ismath:

On Thu, Nov 6, 2008 at 11:40 AM, Andrew Stock > <matplotlib_dev@...663...> wrote:

Thanks Michael,

I've attached a new diff file which I believe also has all the
necessary changes to the collections and images. I've also attached
two simple scripts which test the collections and image functionality.

I've had to make some modification to extension code in this patch
which is definitely not my area of expertise so it would be worth
someone more experienced casting an eye over this.

I've tested this on Linux and successfully run the backend_driver.py
file (or at least, it failed with the same errors as before I applied
the patch!).

Any other comments welcome

Thanks

On Wed, Nov 5, 2008 at 2:31 PM, Michael Droettboom <mdroe@...31...> wrote:

This looks great to me. I can confirm that this works on Linux as well.

I think from here it's just a matter of applying the same pattern of changes
to collections and images. Once that's done, I'm happy to apply the patch.
And if you plan to make a lot of changes in the future, it generally pretty
easy to get commit access. Just ask.

Mike

Andrew Stock wrote:

Hi,

I've attached a diff file which implements the basic functionality. It
currently doesn't handle collections or draw_image, but I wanted to
get something simple working first, before expanding the scope. A
simple test program is as follows:

from pylab import *

f = figure()
a,b = bar([1,2], [2,5], url='http://www.bbc.co.uk/')

a.set_url('http://www.google.com')

f.canvas.print_figure(r'c:\test.svg')

I'd be interested in comments / feedback on the attached before I
start to branch out into more significant changes!

Thanks

Andrew

On Thu, Oct 30, 2008 at 8:02 PM, Michael Droettboom <mdroe@...31...> >>>> wrote:

I realised in my earlier message, I didn't really address your initial
request for feedback on your approach.

I think the goal here should be to make the url support as pervasive as
possible wrt both plot types and backends.

Many of the high-level plotting functions (such as bar()) take a standard
set of "Artist" keywords. In the docs, you'll often see a table like the
one at the bottom for bar():

http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.bar

This support all happens automatically simply by adding a setter and
getter
to the "Artist" class. So, in Artist, simply add set_url/get_url methods
and a private attribute to store the url. You shouldn't have to touch
any
of the high-level plotting functions to have this supported everywhere
where
it makes sense.

Then, to use the url value, you'll want to store it in a GraphicsContext
object to pass to the backend. So you'll want to add an attribute and
getter/setter in GraphicsContextBase as well.

All of the places where the front-end creates a gc and passes it to the
backend will need to be updated (such as Artist.draw, Text.draw, perhaps
others, do a grep for the public methods in RendererBase). Where it sets
things like facecolor on the GraphicsContext, it should also set a url.

Then, in backends where appropriate you would use the url value if
present.
You could start with SVG, and maybe someone can come along and add PDF
support later.

An additional complication for completeness is handling Collections.
Collections store a list of graphics context information (facecolor,
edgecolor etc.) rather than a single one. Therefore, you'll want to add
set_urls/get_urls to Collection as well, and then deal with passing those
values to the backend. Collections don't use a GraphicsContext class, so
you'll need to add a new arg to draw_path_collection in all backends.
(Refactoring this so we pass an object to the backends rather than a
long
list of arguments would be welcome to avoid needing to update multiple
backends for these sorts of new features in the future). You will also
need
to update RendererBase._iter_collection to support iterating over URLs in
the same way as everything else there.

draw_image also doesn't use a gc, so you'll need to add an argument
there.

Hope that gives you a road map... Please let me know if I can help
further.

Mike

Andrew Stock wrote:

Hi,

I have a requirement to make clickable bar charts using the SVG output
(rather than html maps).

An initial look has suggested that the following changes would be
required:

backend_bases.py: Add a url property to GraphicsContextBase
(defaulting to None, so it's all backwards compatible)
axes.py: Add a url option to the bar function and pass this on to the
constructor of the Rectangle object
patches.py: Pass the url option in the constructor for the Patch
object to the GraphicsContextBase object created in the draw function
backends/backend_svg.py: Add check to _draw_svg_element for url set in
gc. If it is, write out SVG code for xlink.

I can make these changes and (if people think it would be useful)
contribute the changes back. However, before I do this, I wanted to
check whether this is the right approach to take - I'm not experienced
with the internals of matplotlib and so if there's a better way of
doing it, I'd be grateful for the advice.

Once I got the bar charts working, I would be interested in possibly
extending this to other chart types.

Regards

Andrew

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's
challenge
Build the coolest Linux based applications with Moblin SDK & win great
prizes
Grand prize is a trip for two to an Open Source event anywhere in the
world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

I went ahead and committed the latest version of your patch. Thanks. This is a cool new feature.

I think it's probably low-risk for having Windows problems, but having it in SVN will make it more likely for Windows users to test.

Cheers,
Mike

Andrew Stock wrote:

···

Jae-Joon,

Thanks for your comments. You have successfully found areas in my
patch that were overcomplicated!

I have attached a new patch which doesn't alter the api of draw_image
and uses the im object as Jae-Joon suggests.

I've tested this on Linux Python 2.5 as before, but not on Windows as
I don't have the correct development environment set up at the moment.

Regards

Andrew

On Fri, Nov 7, 2008 at 10:36 AM, Jae-Joon Lee <lee.j.joon@...149...> wrote:
  

Andrew,

I just had a quick look at your patch.
I'm a bit distracted with your changes regarding the "url" support of the image.
Do we need to change the api of the draw_image()? Can we just utilize
"im" object as we did with the "gc"? Check the patch below. This
simple method seem to work fine for me.

I also noted that, in the __init__() methods of the Patch and the
AxesImage class, you explicitly declare "url" as a keyword argument
and also initialize self.url. I don't think these are necessary as
"url" is already a property of the Artist class.

IHTH,

-JJ

Index: lib/matplotlib/image.py

--- lib/matplotlib/image.py (revision 6361)
+++ lib/matplotlib/image.py (working copy)
@@ -234,6 +234,7 @@
            self.axes.get_yscale() != 'linear'):
            warnings.warn("Images are not supported on non-linear axes.")
        im = self.make_image(renderer.get_image_magnification())
+ im._url = self.get_url()
        l, b, widthDisplay, heightDisplay = self.axes.bbox.bounds
        renderer.draw_image(round(l), round(b), im, self.axes.bbox.frozen(),
                            *self.get_transformed_clip_path_and_affine())
Index: lib/matplotlib/backends/backend_svg.py

--- lib/matplotlib/backends/backend_svg.py (revision 6361)
+++ lib/matplotlib/backends/backend_svg.py (working copy)
@@ -274,6 +283,9 @@

        h,w = im.get_size_out()

+ url = im._url
+ if url is not None:
+ self._svgwriter.write('<a xlink:href="%s">' % url)
        self._svgwriter.write (
            '<image x="%f" y="%f" width="%f" height="%f" '
            '%s xlink:href="'%(x/trans[0],
(self.height-y)/trans[3]-h, w, h, transstr)
@@ -298,6 +310,8 @@
            self._svgwriter.write(filename)

        self._svgwriter.write('"/>\n')
+ if url is not None:
+ self._svgwriter.write('</a>')

    def draw_text(self, gc, x, y, s, prop, angle, ismath):
        if ismath:

On Thu, Nov 6, 2008 at 11:40 AM, Andrew Stock >> <matplotlib_dev@...663...> wrote:
    

Thanks Michael,

I've attached a new diff file which I believe also has all the
necessary changes to the collections and images. I've also attached
two simple scripts which test the collections and image functionality.

I've had to make some modification to extension code in this patch
which is definitely not my area of expertise so it would be worth
someone more experienced casting an eye over this.

I've tested this on Linux and successfully run the backend_driver.py
file (or at least, it failed with the same errors as before I applied
the patch!).

Any other comments welcome

Thanks

On Wed, Nov 5, 2008 at 2:31 PM, Michael Droettboom <mdroe@...31...> wrote:
      

This looks great to me. I can confirm that this works on Linux as well.

I think from here it's just a matter of applying the same pattern of changes
to collections and images. Once that's done, I'm happy to apply the patch.
And if you plan to make a lot of changes in the future, it generally pretty
easy to get commit access. Just ask.

Mike

Andrew Stock wrote:
        

Hi,

I've attached a diff file which implements the basic functionality. It
currently doesn't handle collections or draw_image, but I wanted to
get something simple working first, before expanding the scope. A
simple test program is as follows:

from pylab import *

f = figure()
a,b = bar([1,2], [2,5], url='http://www.bbc.co.uk/')

a.set_url('http://www.google.com')

f.canvas.print_figure(r'c:\test.svg')

I'd be interested in comments / feedback on the attached before I
start to branch out into more significant changes!

Thanks

Andrew

On Thu, Oct 30, 2008 at 8:02 PM, Michael Droettboom <mdroe@...31...> >>>>> wrote:

I realised in my earlier message, I didn't really address your initial
request for feedback on your approach.

I think the goal here should be to make the url support as pervasive as
possible wrt both plot types and backends.

Many of the high-level plotting functions (such as bar()) take a standard
set of "Artist" keywords. In the docs, you'll often see a table like the
one at the bottom for bar():

http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.bar

This support all happens automatically simply by adding a setter and
getter
to the "Artist" class. So, in Artist, simply add set_url/get_url methods
and a private attribute to store the url. You shouldn't have to touch
any
of the high-level plotting functions to have this supported everywhere
where
it makes sense.

Then, to use the url value, you'll want to store it in a GraphicsContext
object to pass to the backend. So you'll want to add an attribute and
getter/setter in GraphicsContextBase as well.

All of the places where the front-end creates a gc and passes it to the
backend will need to be updated (such as Artist.draw, Text.draw, perhaps
others, do a grep for the public methods in RendererBase). Where it sets
things like facecolor on the GraphicsContext, it should also set a url.

Then, in backends where appropriate you would use the url value if
present.
You could start with SVG, and maybe someone can come along and add PDF
support later.

An additional complication for completeness is handling Collections.
Collections store a list of graphics context information (facecolor,
edgecolor etc.) rather than a single one. Therefore, you'll want to add
set_urls/get_urls to Collection as well, and then deal with passing those
values to the backend. Collections don't use a GraphicsContext class, so
you'll need to add a new arg to draw_path_collection in all backends.
(Refactoring this so we pass an object to the backends rather than a
long
list of arguments would be welcome to avoid needing to update multiple
backends for these sorts of new features in the future). You will also
need
to update RendererBase._iter_collection to support iterating over URLs in
the same way as everything else there.

draw_image also doesn't use a gc, so you'll need to add an argument
there.

Hope that gives you a road map... Please let me know if I can help
further.

Mike

Andrew Stock wrote:

Hi,

I have a requirement to make clickable bar charts using the SVG output
(rather than html maps).

An initial look has suggested that the following changes would be
required:

backend_bases.py: Add a url property to GraphicsContextBase
(defaulting to None, so it's all backwards compatible)
axes.py: Add a url option to the bar function and pass this on to the
constructor of the Rectangle object
patches.py: Pass the url option in the constructor for the Patch
object to the GraphicsContextBase object created in the draw function
backends/backend_svg.py: Add check to _draw_svg_element for url set in
gc. If it is, write out SVG code for xlink.

I can make these changes and (if people think it would be useful)
contribute the changes back. However, before I do this, I wanted to
check whether this is the right approach to take - I'm not experienced
with the internals of matplotlib and so if there's a better way of
doing it, I'd be grateful for the advice.

Once I got the bar charts working, I would be interested in possibly
extending this to other chart types.

Regards

Andrew

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's
challenge
Build the coolest Linux based applications with Moblin SDK & win great
prizes
Grand prize is a trip for two to an Open Source event anywhere in the
world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA