Most generic way to wrap collections

Hi,

I am working on a library for image analysis which stores particles as indexed numpy arrays and provides functionality for managing the particles beyond merely image masking or altering the arrays directly. I’ve already designed classes for many common shapes including Lines/Curves, Circles/Ellipses, Polygons, Multi-shapes (eg 4 circles with variable overlap).

What I’d really LOVE to do would be able to generate a matplotlib.Collection instance from these objects as generally as possible. Then, I’d be able to show data as a masked image, but also get a really nice looking plot from the objects in their Collection representation.

So my question really is in the implementation. First, is there a general collection object that could work with ANY shape, or am I better off matching my shape to that collection? For example:

line --> LineCollection vs. line --> GeneralCollection

circle --> CircleCollection circle —> GeneralCollection

And then, is the Collections plotting API flexible enough to mix all of these types together? Or would I have to settle for only being able to plot a collection of any 1 shape type at at time?

I will delve into the API further, but ascertaining this information would really help me get started.

Thanks

Sorry, quick followup. I did find the gallery example to plot multiple patches together:

http://matplotlib.org/examples/api/patch_collection.html

That’s excellent. Now I guess my question is how best to generalize the process of turning my objects into patches. I think I will just try to keep the geometry (ie line → mpatch.Line) unless anyone has any better suggestions.

Thanks!

···

On Tue, Jan 7, 2014 at 3:08 PM, Adam Hughes <hughesadam87@…287…> wrote:

Hi,

I am working on a library for image analysis which stores particles as indexed numpy arrays and provides functionality for managing the particles beyond merely image masking or altering the arrays directly. I’ve already designed classes for many common shapes including Lines/Curves, Circles/Ellipses, Polygons, Multi-shapes (eg 4 circles with variable overlap).

What I’d really LOVE to do would be able to generate a matplotlib.Collection instance from these objects as generally as possible. Then, I’d be able to show data as a masked image, but also get a really nice looking plot from the objects in their Collection representation.

So my question really is in the implementation. First, is there a general collection object that could work with ANY shape, or am I better off matching my shape to that collection? For example:

line → LineCollection vs. line → GeneralCollection

circle → CircleCollection circle —> GeneralCollection

And then, is the Collections plotting API flexible enough to mix all of these types together? Or would I have to settle for only being able to plot a collection of any 1 shape type at at time?

I will delve into the API further, but ascertaining this information would really help me get started.

Thanks

Adam,

Not sure if this is the try you’re trying to bark up, but I’ve used a total hack to do what I think you’re describing:

  1. store lists of coordinate pairs in a pandas DataFrame

  2. use df.apply() to turn each list of coords in to a patch and add to an axes object

I’m sure you know this, but for posterity’s sake, I’ll mention that you really should only store primitives in pandas DataFrames. For that reason alone, I would describe the method above as the death-throes of a failing project trying to meet deadlines.

Perhaps a more robust way would be to store the coordinates in a “long” format, i.e.,

shapeid, vertexid, x, y

1,1,0,0

1,2,1,1

1,3,2,2

2,1,10,10

2,2,11,11

3,3,12,12

And the group that DataFrame by shapeid and use apply on the pandas GroupBy object to construct a patch and add it to an axes object.

Just a thought.

···

On Tue, Jan 7, 2014 at 12:29 PM, Adam Hughes <hughesadam87@…287…> wrote:

Sorry, quick followup. I did find the gallery example to plot multiple patches together:

http://matplotlib.org/examples/api/patch_collection.html

That’s excellent. Now I guess my question is how best to generalize the process of turning my objects into patches. I think I will just try to keep the geometry (ie line → mpatch.Line) unless anyone has any better suggestions.

Thanks!


Rapidly troubleshoot problems before they affect your business. Most IT

organizations don’t have a clear picture of how application performance

affects their revenue. With AppDynamics, you get 100% visibility into your

Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!

http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

On Tue, Jan 7, 2014 at 3:08 PM, Adam Hughes <hughesadam87@…287…> wrote:

Hi,

I am working on a library for image analysis which stores particles as indexed numpy arrays and provides functionality for managing the particles beyond merely image masking or altering the arrays directly. I’ve already designed classes for many common shapes including Lines/Curves, Circles/Ellipses, Polygons, Multi-shapes (eg 4 circles with variable overlap).

What I’d really LOVE to do would be able to generate a matplotlib.Collection instance from these objects as generally as possible. Then, I’d be able to show data as a masked image, but also get a really nice looking plot from the objects in their Collection representation.

So my question really is in the implementation. First, is there a general collection object that could work with ANY shape, or am I better off matching my shape to that collection? For example:

line → LineCollection vs. line → GeneralCollection

circle → CircleCollection circle —> GeneralCollection

And then, is the Collections plotting API flexible enough to mix all of these types together? Or would I have to settle for only being able to plot a collection of any 1 shape type at at time?

I will delve into the API further, but ascertaining this information would really help me get started.

Thanks

Sorry, quick followup. I did find the gallery example to plot multiple
patches together:

http://matplotlib.org/examples/api/patch_collection.html

That's excellent. Now I guess my question is how best to generalize the
process of turning my objects into patches. I think I will just try to
keep the geometry (ie line --> mpatch.Line) unless anyone has any better
suggestions.

As you've already found out, it sounds like you want a PatchCollection.

There is one catch, though. Your lines/curves will need to be converted to
PathPatches (which is trivial), which can then have a facecolor. Because
all items in a collection will have the same facecolor by default, this
means that your lines will become "filled" polygons, unless you specify
otherwise.

Therefore, you'll need to do something like this:

import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as mpatches
from matplotlib.collections import PatchCollection

# Just a simple line, but it could be a bezier curve, etc.
line = Path([(-20, -20), (-10, 10), (20, 20)])

# We'll need to convert the line to a PathPatch, and we'll throw in a
circle, too
line = mpatches.PathPatch(line)
circle = mpatches.Circle([0, 0])

# If we don't specify facecolor='none' for the line, it will be filled!
col = PatchCollection([line, circle], facecolors=['none', 'red'])

fig, ax = plt.subplots()
ax.add_collection(col)
ax.autoscale()
plt.show()

Alternatively, you can just put the lines/curves in a PathCollection and
the patches/polygons/etc in a PatchCollection.

Hope that helps!
-Joe

···

On Tue, Jan 7, 2014 at 2:29 PM, Adam Hughes <hughesadam87@...287...> wrote:

Thanks!

On Tue, Jan 7, 2014 at 3:08 PM, Adam Hughes <hughesadam87@...287...>wrote:

Hi,

I am working on a library for image analysis which stores particles as
indexed numpy arrays and provides functionality for managing the particles
beyond merely image masking or altering the arrays directly. I've already
designed classes for many common shapes including Lines/Curves,
Circles/Ellipses, Polygons, Multi-shapes (eg 4 circles with variable
overlap).

What I'd really LOVE to do would be able to generate a
matplotlib.Collection instance from these objects as generally as possible.
Then, I'd be able to show data as a masked image, but also get a really
nice looking plot from the objects in their Collection representation.

So my question really is in the implementation. First, is there a
general collection object that could work with ANY shape, or am I better
off matching my shape to that collection? For example:

    line --> LineCollection *vs.* line --> GeneralCollection
    circle --> CircleCollection circle ---> GeneralCollection

And then, is the Collections plotting API flexible enough to mix all of
these types together? Or would I have to settle for only being able to
plot a collection of any 1 shape type at at time?

I will delve into the API further, but ascertaining this information
would really help me get started.

Thanks

------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT
organizations don't have a clear picture of how application performance
affects their revenue. With AppDynamics, you get 100% visibility into your
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics
Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
matplotlib-users List Signup and Options

Sorry, had forgot to reply all:

Thanks Joe, that’s perfect. I appreciate the tip, as I would not have realized I needed a PathCollection for lines and curves. PS, do you know if it is possible to have a background image behind a plot of patches? I know it’s doable for scatter, but hadn’t seen an example for patch plots in general.

Paul, thanks for you help as well. I’m actually pretty confident in the primitives I’ve chosen. I was inspired by scikit-image.draw:

http://scikit-image.org/docs/dev/api/skimage.draw.html

Which returns the indicies of an array, such that anytime one ones to draw the array, they merely pass by index. For example:

image = np.zeroes( (256, 256) )

rr, cc = draw.circle( center=(128,128), radius=5)

image[rr, cc] = (1, 0, 0)

The code above would generate a red circle. My library creates primitive classes that have an rr, cc attribute, with enough metadata to hide effectively bury this representation. This can be generated a number of ways, but the classes take care of all of this, as well as other aspects. By keeping only these indicies as primitives, the shapes can be manipulated and managed outside of any representation (ie the image). What I’d like to do is build wrappers to return PatchCollections from my already storred rr, cc data (and other metadata that is stored). In this way, I’ll be able to add the very nice patches from matplotlib, but retain the same api.

The project is called “pyparty” and I’ll share it pretty soon with the scikit image mailing list. If I am able to get the patches built it, would anyone mind if I share it with the matplotlib list as well?

Thanks

···

On Tue, Jan 7, 2014 at 4:10 PM, Joe Kington <joferkington@…287…> wrote:

On Tue, Jan 7, 2014 at 2:29 PM, Adam Hughes <hughesadam87@…287…> wrote:

Sorry, quick followup. I did find the gallery example to plot multiple patches together:

http://matplotlib.org/examples/api/patch_collection.html

That’s excellent. Now I guess my question is how best to generalize the process of turning my objects into patches. I think I will just try to keep the geometry (ie line → mpatch.Line) unless anyone has any better suggestions.

As you’ve already found out, it sounds like you want a PatchCollection.

There
is one catch, though. Your lines/curves will need to be converted to PathPatches (which is trivial), which can then have a facecolor. Because all items in a collection will have the same facecolor by default, this means that your lines will become “filled” polygons, unless you specify otherwise.

Therefore, you’ll need to do something like this:

import matplotlib.pyplot as plt

from matplotlib.path import Path
import matplotlib.patches as mpatches

from matplotlib.collections import PatchCollection

Just a simple line, but it could be a bezier curve, etc.

line = Path([(-20, -20), (-10, 10), (20, 20)])

We’ll need to convert the line to a PathPatch, and we’ll throw in a circle, too

line = mpatches.PathPatch(line)

circle = mpatches.Circle([0, 0])

If we don’t specify facecolor=‘none’ for the line, it will be filled!

col = PatchCollection([line, circle], facecolors=[‘none’, ‘red’])

fig, ax = plt.subplots()

ax.add_collection(col)
ax.autoscale()

plt.show()

Alternatively, you can just put the lines/curves in a PathCollection and the patches/polygons/etc in a PatchCollection.

Hope that helps!

-Joe

Thanks!


Rapidly troubleshoot problems before they affect your business. Most IT

organizations don’t have a clear picture of how application performance

affects their revenue. With AppDynamics, you get 100% visibility into your

Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!

http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

On Tue, Jan 7, 2014 at 3:08 PM, Adam Hughes <hughesadam87@…287…> wrote:

Hi,

I am working on a library for image analysis which stores particles as indexed numpy arrays and provides functionality for managing the particles beyond merely image masking or altering the arrays directly. I’ve already designed classes for many common shapes including Lines/Curves, Circles/Ellipses, Polygons, Multi-shapes (eg 4 circles with variable overlap).

What I’d really LOVE to do would be able to generate a matplotlib.Collection instance from these objects as generally as possible. Then, I’d be able to show data as a masked image, but also get a really nice looking plot from the objects in their Collection representation.

So my question really is in the implementation. First, is there a general collection object that could work with ANY shape, or am I better off matching my shape to that collection? For example:

line → LineCollection vs. line → GeneralCollection

circle → CircleCollection circle —> GeneralCollection

And then, is the Collections plotting API flexible enough to mix all of these types together? Or would I have to settle for only being able to plot a collection of any 1 shape type at at time?

I will delve into the API further, but ascertaining this information would really help me get started.

Thanks