New plot type idea -- EventRaster

I would like to add a new plot type to matplotlib. Of course I am willing to implement it myself, but I want to confirm that it is acceptable and iron out the implementation details and API first so there are no major surprises when I submit it.

I tentatively am calling the plot type an “EventRaster” plot (name suggestions, along with any other suggestions, are welcome). The plot is made up if horizontal rows of identical vertical lines and/or markers. Each line or marker represents a discrete event, and each row represents a single sequence of events (such as a trial). The x-axis position of the line or marker identifies the location of the event by some measure. An example of what such a plot often looks like is below.

http://hebb.mit.edu/courses/9.29/2003/athena/dylanh/quad-rast.gif

This
sort of plot is used ubiquitously in neuroscience. It is used to show the time of discrete neural (brain cell) events (called “spikes”) over time in repeated trials, and is generally called a spike raster, raster plot, or raster graph. However, it can be used in any situation where you are only concerned with the position of events but not their amplitude, especially if you want to look for patterns in those events or look for differences between multiple sequences of events.

Plotting the timing of events is an obvious use case, such as photons hitting photodetectors, radioactive decay events, arrival of patients to hospitals, calls to hotlines, or car accidents in cities. However, the events do not have to be relative to time. It could be position, for example, such as tree rings along bore holes, road crossings along railroad tracks, layers in sediment cores, or particular sequences along a DNA strands.

I’ll cover possible implementation details in the next email if everyone thinks this is a good idea.

This is very closely related to "rug plots", which are often used as
an axis annotation or elsewhere where it's nice to have a small 1-d
density plot. Examples:
  https://www.cl.cam.ac.uk/~sjm217/projects/graphics/
  http://rforge.org/2009/08/10/fancy-rugs-in-regression-plots/

-n

···

On Mon, Sep 24, 2012 at 2:33 PM, Todd <toddrjen@...149...> wrote:

This sort of plot is used ubiquitously in neuroscience. It is used to show
the time of discrete neural (brain cell) events (called "spikes") over time
in repeated trials, and is generally called a spike raster, raster plot, or
raster graph. However, it can be used in any situation where you are only
concerned with the position of events but not their amplitude, especially if
you want to look for patterns in those events or look for differences
between multiple sequences of events.

The implementation I am thinking of for this plot type would also be
able to handle these sorts of plots, although it would probably
require creating horizontal and vertical variants.

···

On Mon, Sep 24, 2012 at 3:51 PM, Nathaniel Smith <njs@...503...> wrote:

On Mon, Sep 24, 2012 at 2:33 PM, Todd <toddrjen@...149...> wrote:

This sort of plot is used ubiquitously in neuroscience. It is used to show
the time of discrete neural (brain cell) events (called "spikes") over time
in repeated trials, and is generally called a spike raster, raster plot, or
raster graph. However, it can be used in any situation where you are only
concerned with the position of events but not their amplitude, especially if
you want to look for patterns in those events or look for differences
between multiple sequences of events.

This is very closely related to "rug plots", which are often used as
an axis annotation or elsewhere where it's nice to have a small 1-d
density plot. Examples:
  https://www.cl.cam.ac.uk/~sjm217/projects/graphics/
  http://rforge.org/2009/08/10/fancy-rugs-in-regression-plots/

So does anyone think this would be a useful plot type? If so I can explain how I plan to implement it and we can discuss changes or improvements to that.

···

On Mon, Sep 24, 2012 at 3:33 PM, Todd <toddrjen@…149…> wrote:

I would like to add a new plot type to matplotlib. Of course I am willing to implement it myself, but I want to confirm that it is acceptable and iron out the implementation details and API first so there are no major surprises when I submit it.

I tentatively am calling the plot type an “EventRaster” plot (name suggestions, along with any other suggestions, are welcome). The plot is made up if horizontal rows of identical vertical lines and/or markers. Each line or marker represents a discrete event, and each row represents a single sequence of events (such as a trial). The x-axis position of the line or marker identifies the location of the event by some measure. An example of what such a plot often looks like is below.

http://hebb.mit.edu/courses/9.29/2003/athena/dylanh/quad-rast.gif

This
sort of plot is used ubiquitously in neuroscience. It is used to show the time of discrete neural (brain cell) events (called “spikes”) over time in repeated trials, and is generally called a spike raster, raster plot, or raster graph. However, it can be used in any situation where you are only concerned with the position of events but not their amplitude, especially if you want to look for patterns in those events or look for differences between multiple sequences of events.

Plotting the timing of events is an obvious use case, such as photons hitting photodetectors, radioactive decay events, arrival of patients to hospitals, calls to hotlines, or car accidents in cities. However, the events do not have to be relative to time. It could be position, for example, such as tree rings along bore holes, road crossings along railroad tracks, layers in sediment cores, or particular sequences along a DNA strands.

I’ll cover possible implementation details in the next email if everyone thinks this is a good idea.

Sorry to not get back to you sooner – a number of us are busy here
getting the 1.2.0 release ready at the moment. I think this is
definitely a worthwhile plot type to add. Similar plots are used in
Computer Science, for example, to visualize the execution of
multi-threaded applications, or other scheduling problems. I’d
personally use it for that.
So, yes, let’s start talking implementation. Or, if easier, you
could just submit a pull request and we can go from there. Whatever
method seems most appropriate to you.
Cheers,
Mike

···

On 09/26/2012 04:35 AM, Todd wrote:

On Mon, Sep 24, 2012 at 3:33 PM, Todd <toddrjen@…149…>
wrote:

      I would like to add a new plot type to matplotlib.  Of course

I am willing to implement it myself, but I want to confirm
that it is acceptable and iron out the implementation details
and API first so there are no major surprises when I submit
it.

      I tentatively am calling the plot type an "EventRaster" plot

(name suggestions, along with any other suggestions, are
welcome). The plot is made up if horizontal rows of identical
vertical lines and/or markers. Each line or marker represents
a discrete event, and each row represents a single sequence of
events (such as a trial). The x-axis position of the line or
marker identifies the location of the event by some measure.
An example of what such a plot often looks like is below.

      [http://hebb.mit.edu/courses/9.29/2003/athena/dylanh/quad-rast.gif](http://hebb.mit.edu/courses/9.29/2003/athena/dylanh/quad-rast.gif)



      This sort of plot is used ubiquitously in neuroscience.  It is

used to show the time of discrete neural (brain cell) events
(called “spikes”) over time in repeated trials, and is
generally called a spike raster, raster plot, or raster
graph. However, it can be used in any situation where you are
only concerned with the position of events but not their
amplitude, especially if you want to look for patterns in
those events or look for differences between multiple
sequences of events.

      Plotting the timing of events is an obvious use case, such as

photons hitting photodetectors, radioactive decay events,
arrival of patients to hospitals, calls to hotlines, or car
accidents in cities. However, the events do not have to be
relative to time. It could be position, for example, such as
tree rings along bore holes, road crossings along railroad
tracks, layers in sediment cores, or particular sequences
along a DNA strands.

      I'll cover possible implementation details in the next email

if everyone thinks this is a good idea.

  So does anyone think this would be a useful plot type?  If so I

can explain how I plan to implement it and we can discuss changes
or improvements to that.

I would prefer to get the details worked out before I start coding
since there are a few different approaches. First thing is to figure
out a good name, I am not sure this is the best name for it.

Assuming we go with the name, here is my proposed call signature:

EventRaster(x, offset=0, height=1, **kargs)

x is a 1D or 2D array. If a 1D array, it create a single row of
lines. If it is a 2D array, it creates one row of lines for each row
in the array.

offset determines the positions of the rows. By default, the first
row is placed with the line center y=0, and subsequent rows are placed
with the line centers at increasing 1-unit increments. If offset is
defined and is a scalar, the first row is placed at the offset, and
subsequent rows are placed at increasing 1-unit increments. If offset
is an array, it must be a 1D array of the same length as the second
dimension of x. In this case each element in offset determines the
center of the corresponding row in the plot.

height determines the length of the lines. By default the line
stretches from offset-.5 to offset+.5. If height is defined the line
stretches from offset-.5*height to offset+.5*height.

**kargs are the same as those of plot().

An important thing to note is that the marker will only appear the
center point of each line, not at the ends.

If this is going to be used to implement rug plots, it would need some
way to handle columns of horizontal lines in addition to rows of
vertical lines. I see two ways to implement this. First is to have
to plot types, perhaps HEventRaster and VEventRaster. The first would
be as described above, while the second would be similar but
everything rotated 90 degrees. Another possibility is to change the
call signature to this:

EventRaster(x, y=None, offset=0, height=1, **kargs)

In this case y behaves the same as x, except it creates columns of
lines instead of rows. If y is specified x cannot be specified, and
vice versus. If keyword arguments are not used, it assumes x is what
is wanted.

I don't know which approach is better.

The function will return a list of a new collection type I am
tentatively calling EventCollection. My thinking would be this would
be a subclass of a new collection type called GenericLineCollection,
which the current LineCollection would also subclass. They would
share things like the color handling and segment handling, however the
segment handling will be a "private" method that LineCollection will
have a public wrapper for. On the other hand methods to set or add
segments will remain private in EventCollection, although there will
be a method to return the segments if an artist really wants to
manipulate individual segments.

The reason for doing it this way is that manipulating individual rows
of events should be very common, such as changing their position,
color, marker, width, and so on. On the other hand manipulating lines
individually should not be as common, although still supported.

Internally, the lines will be length 3 Line2D objects, with the 3
points being offset-.5*height, offset, and offset+.5*height.

So what does everyone think of this approach? Does anyone have any
comments, suggestions, or just think the approach is nonsense? It
would certainly be possible to implement this based more on existing
classes, but I don't think the implementation would be as clean, as
maintainable, or as extensible as this implementation.

···

On Wed, Sep 26, 2012 at 3:14 PM, Michael Droettboom <mdroe@...31...> wrote:

On 09/26/2012 04:35 AM, Todd wrote:

On Mon, Sep 24, 2012 at 3:33 PM, Todd <toddrjen@...149...> wrote:

I would like to add a new plot type to matplotlib. Of course I am willing
to implement it myself, but I want to confirm that it is acceptable and iron
out the implementation details and API first so there are no major surprises
when I submit it.

I tentatively am calling the plot type an "EventRaster" plot (name
suggestions, along with any other suggestions, are welcome). The plot is
made up if horizontal rows of identical vertical lines and/or markers. Each
line or marker represents a discrete event, and each row represents a single
sequence of events (such as a trial). The x-axis position of the line or
marker identifies the location of the event by some measure. An example of
what such a plot often looks like is below.

http://hebb.mit.edu/courses/9.29/2003/athena/dylanh/quad-rast.gif

This sort of plot is used ubiquitously in neuroscience. It is used to
show the time of discrete neural (brain cell) events (called "spikes") over
time in repeated trials, and is generally called a spike raster, raster
plot, or raster graph. However, it can be used in any situation where you
are only concerned with the position of events but not their amplitude,
especially if you want to look for patterns in those events or look for
differences between multiple sequences of events.

Plotting the timing of events is an obvious use case, such as photons
hitting photodetectors, radioactive decay events, arrival of patients to
hospitals, calls to hotlines, or car accidents in cities. However, the
events do not have to be relative to time. It could be position, for
example, such as tree rings along bore holes, road crossings along railroad
tracks, layers in sediment cores, or particular sequences along a DNA
strands.

I'll cover possible implementation details in the next email if everyone
thinks this is a good idea.

So does anyone think this would be a useful plot type? If so I can explain
how I plan to implement it and we can discuss changes or improvements to
that.

Sorry to not get back to you sooner -- a number of us are busy here getting
the 1.2.0 release ready at the moment. I think this is definitely a
worthwhile plot type to add. Similar plots are used in Computer Science,
for example, to visualize the execution of multi-threaded applications, or
other scheduling problems. I'd personally use it for that.

So, yes, let's start talking implementation. Or, if easier, you could just
submit a pull request and we can go from there. Whatever method seems most
appropriate to you.

As someone from a field that doesn't regularly use that sort of plot,
'raster' seems an odd name - it doesn't seem to relate to raster vs.
vector graphics. From the examples linked earlier in the thread, I'd
call it something like EventStrip.

Thanks,
Thomas

···

On 27 September 2012 11:41, Todd <toddrjen@...149...> wrote:

I would prefer to get the details worked out before I start coding
since there are a few different approaches. First thing is to figure
out a good name, I am not sure this is the best name for it.

I would prefer to get the details worked out before I start coding
since there are a few different approaches. First thing is to figure
out a good name, I am not sure this is the best name for it.

As someone from a field that doesn't regularly use that sort of plot,
'raster' seems an odd name - it doesn't seem to relate to raster vs.
vector graphics.

That was exactly my concern.

From the examples linked earlier in the thread, I'd
call it something like EventStrip.

The problem is it isn't really a strip either, since it can have many
rows of events. It could be EventStrips, though.

Some other possibilities that occured to me:

EventPlot
EventsPlot
SequencePlot
SequencesPlot
Events1D
Sequences1D

···

On Thu, Sep 27, 2012 at 12:58 PM, Thomas Kluyver <thomas@...1071...> wrote:

On 27 September 2012 11:41, Todd <toddrjen@...149...> wrote:

Hi Todd,

Firstly, thanks for taking the time to crystallise your thoughts in
words first. This is one of my bad habits; I tend to rush into things.

I have some feedback for you, hopefully we can all work together to
get this right. It's difficult when something new gets implemented and
someone expects it to do something and the only way to resolve it is
to break the calling API. Anyway, I hope you'll find my comments
helpful at the least. I also encourage others to weigh in with
opinions and ideas.

Assuming we go with the name, here is my proposed call signature:

EventRaster(x, offset=0, height=1, **kargs)

CamelCase is discouraged for method names. Perhaps 'eventraster'?

Also, we could also let **kwargs swallow the 'offset' and 'height'
keyword arguments. Then the user isn't constrained by which order to
put them in. The downside of this approach is that introspection is
more difficult.

x is a 1D or 2D array. If a 1D array, it create a single row of
lines. If it is a 2D array, it creates one row of lines for each row
in the array.

Good. I like this.

offset determines the positions of the rows. By default, the first
row is placed with the line center y=0, and subsequent rows are placed
with the line centers at increasing 1-unit increments. If offset is
defined and is a scalar, the first row is placed at the offset, and
subsequent rows are placed at increasing 1-unit increments. If offset
is an array, it must be a 1D array of the same length as the second
dimension of x. In this case each element in offset determines the
center of the corresponding row in the plot.

How about letting offset be either: a) a scalar, determining the
offset of all rows equally; or b) an array, determining the offset of
each row individually. In fact, why plot each row at integer y
coordinates? Could we allow for an optional y-coordinate array, each
element of which would be the y-coordinate at which to plot a row of
lines. Then you wouldn't need offset.

height determines the length of the lines. By default the line
stretches from offset-.5 to offset+.5. If height is defined the line
stretches from offset-.5*height to offset+.5*height.

Fair enough; sensible defaults.

**kargs are the same as those of plot().

Good. I like this modular approach.

If this is going to be used to implement rug plots, it would need some
way to handle columns of horizontal lines in addition to rows of
vertical lines. I see two ways to implement this. First is to have
to plot types, perhaps HEventRaster and VEventRaster. The first would
be as described above, while the second would be similar but
everything rotated 90 degrees. Another possibility is to change the
call signature to this:

EventRaster(x, y=None, offset=0, height=1, **kargs)

I think accepting an 'orientation' kwarg, which can take either
'horizontal' or 'vertical', determining the orientation of the lines
and reversing the roles of the x and y arrays.

In this case y behaves the same as x, except it creates columns of
lines instead of rows. If y is specified x cannot be specified, and
vice versus. If keyword arguments are not used, it assumes x is what
is wanted.

I don't know which approach is better.

Me neither.

The function will return a list of a new collection type I am
tentatively calling EventCollection. My thinking would be this would
be a subclass of a new collection type called GenericLineCollection,
which the current LineCollection would also subclass. They would
share things like the color handling and segment handling, however the
segment handling will be a "private" method that LineCollection will
have a public wrapper for. On the other hand methods to set or add
segments will remain private in EventCollection, although there will
be a method to return the segments if an artist really wants to
manipulate individual segments.

Why can't we just use LineCollection? I don't see a good reason to
create a new collection class here; the plot is simple.

The reason for doing it this way is that manipulating individual rows
of events should be very common, such as changing their position,
color, marker, width, and so on. On the other hand manipulating lines
individually should not be as common, although still supported.

Fair enough, then maybe a better idea is to create your own
EventRaster class (note camel case) to hold all the relevant data in
arrays. Then make a 'construct_raster' method could return a
LineCollection. Then again, weren't you passing extra kwargs to
'plot'? This approach would surely use ax.add_lines or
ax.add_linecollection something (I can't remember what it's called).

Internally, the lines will be length 3 Line2D objects, with the 3
points being offset-.5*height, offset, and offset+.5*height.

So what does everyone think of this approach? Does anyone have any
comments, suggestions, or just think the approach is nonsense? It
would certainly be possible to implement this based more on existing
classes, but I don't think the implementation would be as clean, as
maintainable, or as extensible as this implementation.

I hope these comments are useful.

Best,
Damon

···

--
Damon McDougall
http://www.damon-is-a-geek.com
B2.39
Mathematics Institute
University of Warwick
Coventry
West Midlands
CV4 7AL
United Kingdom

Hi Todd,

Firstly, thanks for taking the time to crystallise your thoughts in
words first. This is one of my bad habits; I tend to rush into things.

I have some feedback for you, hopefully we can all work together to
get this right. It's difficult when something new gets implemented and
someone expects it to do something and the only way to resolve it is
to break the calling API.

Where is API broken?

Anyway, I hope you'll find my comments
helpful at the least. I also encourage others to weigh in with
opinions and ideas.

Okay, I will discuss the rationale. I will snip out anything you
agree on for brevity.

Assuming we go with the name, here is my proposed call signature:

EventRaster(x, offset=0, height=1, **kargs)

CamelCase is discouraged for method names. Perhaps 'eventraster'?

Fair enough.

Also, we could also let **kwargs swallow the 'offset' and 'height'
keyword arguments. Then the user isn't constrained by which order to
put them in. The downside of this approach is that introspection is
more difficult.

I don't understand the advantage of this approach. If you use keyword
arguments, then the order doesn't matter. So with the approach above
you can use keyword arguments, in which case you can use whatever
order they want, or you can use positional arguments. On the other
hand putting it in **kwargs, we lose the ability to use positional
arguments. So we lose nothing by allowing both positional and keyword
arguments. It is also easier to implement.

offset determines the positions of the rows. By default, the first
row is placed with the line center y=0, and subsequent rows are placed
with the line centers at increasing 1-unit increments. If offset is
defined and is a scalar, the first row is placed at the offset, and
subsequent rows are placed at increasing 1-unit increments. If offset
is an array, it must be a 1D array of the same length as the second
dimension of x. In this case each element in offset determines the
center of the corresponding row in the plot.

How about letting offset be either: a) a scalar, determining the
offset of all rows equally; or b) an array, determining the offset of
each row individually.

Because people are almost never going to want to have all the lines
stacked right on top of each other. The plot would be indecipherable
that way. The defaults are chosen to handle the most common use-cases
most easily.

In fact, why plot each row at integer y
coordinates? Could we allow for an optional y-coordinate array, each
element of which would be the y-coordinate at which to plot a row of
lines. Then you wouldn't need offset.

That is exactly what offset does if you pass an array.

If this is going to be used to implement rug plots, it would need some
way to handle columns of horizontal lines in addition to rows of
vertical lines. I see two ways to implement this. First is to have
to plot types, perhaps HEventRaster and VEventRaster. The first would
be as described above, while the second would be similar but
everything rotated 90 degrees. Another possibility is to change the
call signature to this:

EventRaster(x, y=None, offset=0, height=1, **kargs)

I think accepting an 'orientation' kwarg, which can take either
'horizontal' or 'vertical', determining the orientation of the lines
and reversing the roles of the x and y arrays.

That would work as well. Probably cleaner that way

The function will return a list of a new collection type I am
tentatively calling EventCollection. My thinking would be this would
be a subclass of a new collection type called GenericLineCollection,
which the current LineCollection would also subclass. They would
share things like the color handling and segment handling, however the
segment handling will be a "private" method that LineCollection will
have a public wrapper for. On the other hand methods to set or add
segments will remain private in EventCollection, although there will
be a method to return the segments if an artist really wants to
manipulate individual segments.

Why can't we just use LineCollection? I don't see a good reason to
create a new collection class here; the plot is simple.

Explained below.

The reason for doing it this way is that manipulating individual rows
of events should be very common, such as changing their position,
color, marker, width, and so on. On the other hand manipulating lines
individually should not be as common, although still supported.

Fair enough, then maybe a better idea is to create your own
EventRaster class (note camel case) to hold all the relevant data in
arrays. Then make a 'construct_raster' method could return a
LineCollection. Then again, weren't you passing extra kwargs to
'plot'? This approach would surely use ax.add_lines or
ax.add_linecollection something (I can't remember what it's called).

The whole point of creating a new collection type is that artists will
be able to manipulate individual sets of events.

For example, with an ordinary LineCollection it will be extremely
difficult to change the marker type, since doing so will change the
marker for all 3 points on each segment rather than just the middle
point. So if someone makes the plot, than wants to set rows to have
different marker types instead of being lines, they can do that if we
use a new collection class. But if we use LineCollection this becomes
much more difficult.

Similarly, with a LineCollection the lines lose their status as
objects with a single distinct position. They become objects with 3
2D coordinates. So if someone wants to add more events to the end,
they need to take care of handling the x and y coordinates, making
sure the x coordinates are the same and taking the y coordinates from
one of the existing lines. Similarly changing the height or vertical
position of all the objects is complicated, having to manually
calculate and modify the y coordinates of each point in each segment.

Again, the idea here is to make the most common use-cases as easy as
possible. LineCollection objects aren't really suited to the sort of
artistic changes that are typical with this sort of plot.

In fact I would say that having a separate collection class is central
to this idea. If users aren't able to manipulate the set of events as
such after they create the plot, then there really isn't any advantage
over just using a vlines plot. Calculating the ymin and ymax is one
line of code each, it is the artistic changes that save many lines of
code and a lot of complexity.

···

On Thu, Sep 27, 2012 at 1:12 PM, Damon McDougall <damon.mcdougall@...149...> wrote:

Hi Todd,

Firstly, thanks for taking the time to crystallise your thoughts in
words first. This is one of my bad habits; I tend to rush into things.

I have some feedback for you, hopefully we can all work together to
get this right. It's difficult when something new gets implemented and
someone expects it to do something and the only way to resolve it is
to break the calling API.

Where is API broken?

Nowhere. I wasn't implying you were breaking something. My point was
that it's easy to add functionality but hard to remove it, therefore
it's important to get it right from the outset. I'm sorry for the
misunderstanding; I wasn't clear.

···

On Thu, Sep 27, 2012 at 12:44 PM, Todd <toddrjen@...149...> wrote:

On Thu, Sep 27, 2012 at 1:12 PM, Damon McDougall > <damon.mcdougall@...149...> wrote:

Anyway, I hope you'll find my comments
helpful at the least. I also encourage others to weigh in with
opinions and ideas.

Okay, I will discuss the rationale. I will snip out anything you
agree on for brevity.

Assuming we go with the name, here is my proposed call signature:

EventRaster(x, offset=0, height=1, **kargs)

CamelCase is discouraged for method names. Perhaps 'eventraster'?

Fair enough.

Also, we could also let **kwargs swallow the 'offset' and 'height'
keyword arguments. Then the user isn't constrained by which order to
put them in. The downside of this approach is that introspection is
more difficult.

I don't understand the advantage of this approach. If you use keyword
arguments, then the order doesn't matter. So with the approach above
you can use keyword arguments, in which case you can use whatever
order they want, or you can use positional arguments. On the other
hand putting it in **kwargs, we lose the ability to use positional
arguments. So we lose nothing by allowing both positional and keyword
arguments. It is also easier to implement.

offset determines the positions of the rows. By default, the first
row is placed with the line center y=0, and subsequent rows are placed
with the line centers at increasing 1-unit increments. If offset is
defined and is a scalar, the first row is placed at the offset, and
subsequent rows are placed at increasing 1-unit increments. If offset
is an array, it must be a 1D array of the same length as the second
dimension of x. In this case each element in offset determines the
center of the corresponding row in the plot.

How about letting offset be either: a) a scalar, determining the
offset of all rows equally; or b) an array, determining the offset of
each row individually.

Because people are almost never going to want to have all the lines
stacked right on top of each other. The plot would be indecipherable
that way. The defaults are chosen to handle the most common use-cases
most easily.

In fact, why plot each row at integer y
coordinates? Could we allow for an optional y-coordinate array, each
element of which would be the y-coordinate at which to plot a row of
lines. Then you wouldn't need offset.

That is exactly what offset does if you pass an array.

If this is going to be used to implement rug plots, it would need some
way to handle columns of horizontal lines in addition to rows of
vertical lines. I see two ways to implement this. First is to have
to plot types, perhaps HEventRaster and VEventRaster. The first would
be as described above, while the second would be similar but
everything rotated 90 degrees. Another possibility is to change the
call signature to this:

EventRaster(x, y=None, offset=0, height=1, **kargs)

I think accepting an 'orientation' kwarg, which can take either
'horizontal' or 'vertical', determining the orientation of the lines
and reversing the roles of the x and y arrays.

That would work as well. Probably cleaner that way

The function will return a list of a new collection type I am
tentatively calling EventCollection. My thinking would be this would
be a subclass of a new collection type called GenericLineCollection,
which the current LineCollection would also subclass. They would
share things like the color handling and segment handling, however the
segment handling will be a "private" method that LineCollection will
have a public wrapper for. On the other hand methods to set or add
segments will remain private in EventCollection, although there will
be a method to return the segments if an artist really wants to
manipulate individual segments.

Why can't we just use LineCollection? I don't see a good reason to
create a new collection class here; the plot is simple.

Explained below.

The reason for doing it this way is that manipulating individual rows
of events should be very common, such as changing their position,
color, marker, width, and so on. On the other hand manipulating lines
individually should not be as common, although still supported.

Fair enough, then maybe a better idea is to create your own
EventRaster class (note camel case) to hold all the relevant data in
arrays. Then make a 'construct_raster' method could return a
LineCollection. Then again, weren't you passing extra kwargs to
'plot'? This approach would surely use ax.add_lines or
ax.add_linecollection something (I can't remember what it's called).

The whole point of creating a new collection type is that artists will
be able to manipulate individual sets of events.

For example, with an ordinary LineCollection it will be extremely
difficult to change the marker type, since doing so will change the
marker for all 3 points on each segment rather than just the middle
point. So if someone makes the plot, than wants to set rows to have
different marker types instead of being lines, they can do that if we
use a new collection class. But if we use LineCollection this becomes
much more difficult.

Similarly, with a LineCollection the lines lose their status as
objects with a single distinct position. They become objects with 3
2D coordinates. So if someone wants to add more events to the end,
they need to take care of handling the x and y coordinates, making
sure the x coordinates are the same and taking the y coordinates from
one of the existing lines. Similarly changing the height or vertical
position of all the objects is complicated, having to manually
calculate and modify the y coordinates of each point in each segment.

Again, the idea here is to make the most common use-cases as easy as
possible. LineCollection objects aren't really suited to the sort of
artistic changes that are typical with this sort of plot.

In fact I would say that having a separate collection class is central
to this idea. If users aren't able to manipulate the set of events as
such after they create the plot, then there really isn't any advantage
over just using a vlines plot. Calculating the ymin and ymax is one
line of code each, it is the artistic changes that save many lines of
code and a lot of complexity.

--
Damon McDougall
http://www.damon-is-a-geek.com
B2.39
Mathematics Institute
University of Warwick
Coventry
West Midlands
CV4 7AL
United Kingdom

No problem. I put a lot of other comments inline in my reply to your
email, but your mail reader might have cut them off.

-Todd

···

On Thu, Sep 27, 2012 at 2:17 PM, Damon McDougall <damon.mcdougall@...149...> wrote:

On Thu, Sep 27, 2012 at 12:44 PM, Todd <toddrjen@...149...> wrote:

On Thu, Sep 27, 2012 at 1:12 PM, Damon McDougall >> <damon.mcdougall@...149...> wrote:

Hi Todd,

Firstly, thanks for taking the time to crystallise your thoughts in
words first. This is one of my bad habits; I tend to rush into things.

I have some feedback for you, hopefully we can all work together to
get this right. It's difficult when something new gets implemented and
someone expects it to do something and the only way to resolve it is
to break the calling API.

Where is API broken?

Nowhere. I wasn't implying you were breaking something. My point was
that it's easy to add functionality but hard to remove it, therefore
it's important to get it right from the outset. I'm sorry for the
misunderstanding; I wasn't clear.

I would also like to add that the new collection object would be
useful outside of this plot type.

For example if someone wanted to create a rug plot as Nathaniel
described, and they want those along the same axes as the main plot,
then they would most likely not be be using the plot function, but
rather creating two individual collection objects in an existing
figure.

I can imagine other cases besides a strict rug plot where adding such
a collection object could be useful.

···

On Thu, Sep 27, 2012 at 1:44 PM, Todd <toddrjen@...149...> wrote:

On Thu, Sep 27, 2012 at 1:12 PM, Damon McDougall > <damon.mcdougall@...149...> wrote:

Hi Todd,

Firstly, thanks for taking the time to crystallise your thoughts in
words first. This is one of my bad habits; I tend to rush into things.

I have some feedback for you, hopefully we can all work together to
get this right. It's difficult when something new gets implemented and
someone expects it to do something and the only way to resolve it is
to break the calling API.

Where is API broken?

Anyway, I hope you'll find my comments
helpful at the least. I also encourage others to weigh in with
opinions and ideas.

Okay, I will discuss the rationale. I will snip out anything you
agree on for brevity.

Assuming we go with the name, here is my proposed call signature:

EventRaster(x, offset=0, height=1, **kargs)

CamelCase is discouraged for method names. Perhaps 'eventraster'?

Fair enough.

Also, we could also let **kwargs swallow the 'offset' and 'height'
keyword arguments. Then the user isn't constrained by which order to
put them in. The downside of this approach is that introspection is
more difficult.

I don't understand the advantage of this approach. If you use keyword
arguments, then the order doesn't matter. So with the approach above
you can use keyword arguments, in which case you can use whatever
order they want, or you can use positional arguments. On the other
hand putting it in **kwargs, we lose the ability to use positional
arguments. So we lose nothing by allowing both positional and keyword
arguments. It is also easier to implement.

offset determines the positions of the rows. By default, the first
row is placed with the line center y=0, and subsequent rows are placed
with the line centers at increasing 1-unit increments. If offset is
defined and is a scalar, the first row is placed at the offset, and
subsequent rows are placed at increasing 1-unit increments. If offset
is an array, it must be a 1D array of the same length as the second
dimension of x. In this case each element in offset determines the
center of the corresponding row in the plot.

How about letting offset be either: a) a scalar, determining the
offset of all rows equally; or b) an array, determining the offset of
each row individually.

Because people are almost never going to want to have all the lines
stacked right on top of each other. The plot would be indecipherable
that way. The defaults are chosen to handle the most common use-cases
most easily.

In fact, why plot each row at integer y
coordinates? Could we allow for an optional y-coordinate array, each
element of which would be the y-coordinate at which to plot a row of
lines. Then you wouldn't need offset.

That is exactly what offset does if you pass an array.

If this is going to be used to implement rug plots, it would need some
way to handle columns of horizontal lines in addition to rows of
vertical lines. I see two ways to implement this. First is to have
to plot types, perhaps HEventRaster and VEventRaster. The first would
be as described above, while the second would be similar but
everything rotated 90 degrees. Another possibility is to change the
call signature to this:

EventRaster(x, y=None, offset=0, height=1, **kargs)

I think accepting an 'orientation' kwarg, which can take either
'horizontal' or 'vertical', determining the orientation of the lines
and reversing the roles of the x and y arrays.

That would work as well. Probably cleaner that way

The function will return a list of a new collection type I am
tentatively calling EventCollection. My thinking would be this would
be a subclass of a new collection type called GenericLineCollection,
which the current LineCollection would also subclass. They would
share things like the color handling and segment handling, however the
segment handling will be a "private" method that LineCollection will
have a public wrapper for. On the other hand methods to set or add
segments will remain private in EventCollection, although there will
be a method to return the segments if an artist really wants to
manipulate individual segments.

Why can't we just use LineCollection? I don't see a good reason to
create a new collection class here; the plot is simple.

Explained below.

The reason for doing it this way is that manipulating individual rows
of events should be very common, such as changing their position,
color, marker, width, and so on. On the other hand manipulating lines
individually should not be as common, although still supported.

Fair enough, then maybe a better idea is to create your own
EventRaster class (note camel case) to hold all the relevant data in
arrays. Then make a 'construct_raster' method could return a
LineCollection. Then again, weren't you passing extra kwargs to
'plot'? This approach would surely use ax.add_lines or
ax.add_linecollection something (I can't remember what it's called).

The whole point of creating a new collection type is that artists will
be able to manipulate individual sets of events.

For example, with an ordinary LineCollection it will be extremely
difficult to change the marker type, since doing so will change the
marker for all 3 points on each segment rather than just the middle
point. So if someone makes the plot, than wants to set rows to have
different marker types instead of being lines, they can do that if we
use a new collection class. But if we use LineCollection this becomes
much more difficult.

Similarly, with a LineCollection the lines lose their status as
objects with a single distinct position. They become objects with 3
2D coordinates. So if someone wants to add more events to the end,
they need to take care of handling the x and y coordinates, making
sure the x coordinates are the same and taking the y coordinates from
one of the existing lines. Similarly changing the height or vertical
position of all the objects is complicated, having to manually
calculate and modify the y coordinates of each point in each segment.

Again, the idea here is to make the most common use-cases as easy as
possible. LineCollection objects aren't really suited to the sort of
artistic changes that are typical with this sort of plot.

In fact I would say that having a separate collection class is central
to this idea. If users aren't able to manipulate the set of events as
such after they create the plot, then there really isn't any advantage
over just using a vlines plot. Calculating the ymin and ymax is one
line of code each, it is the artistic changes that save many lines of
code and a lot of complexity.

Now that 1.2 is out, can we revisit this? I would like to get it
implemented for the next feature release.

-Todd

···

On Thu, Sep 27, 2012 at 8:18 PM, Todd <toddrjen@...149...> wrote:

On Thu, Sep 27, 2012 at 1:44 PM, Todd <toddrjen@...149...> wrote:

On Thu, Sep 27, 2012 at 1:12 PM, Damon McDougall >> <damon.mcdougall@...149...> wrote:

Hi Todd,

Firstly, thanks for taking the time to crystallise your thoughts in
words first. This is one of my bad habits; I tend to rush into things.

I have some feedback for you, hopefully we can all work together to
get this right. It's difficult when something new gets implemented and
someone expects it to do something and the only way to resolve it is
to break the calling API.

Where is API broken?

Anyway, I hope you'll find my comments
helpful at the least. I also encourage others to weigh in with
opinions and ideas.

Okay, I will discuss the rationale. I will snip out anything you
agree on for brevity.

Assuming we go with the name, here is my proposed call signature:

EventRaster(x, offset=0, height=1, **kargs)

CamelCase is discouraged for method names. Perhaps 'eventraster'?

Fair enough.

Also, we could also let **kwargs swallow the 'offset' and 'height'
keyword arguments. Then the user isn't constrained by which order to
put them in. The downside of this approach is that introspection is
more difficult.

I don't understand the advantage of this approach. If you use keyword
arguments, then the order doesn't matter. So with the approach above
you can use keyword arguments, in which case you can use whatever
order they want, or you can use positional arguments. On the other
hand putting it in **kwargs, we lose the ability to use positional
arguments. So we lose nothing by allowing both positional and keyword
arguments. It is also easier to implement.

offset determines the positions of the rows. By default, the first
row is placed with the line center y=0, and subsequent rows are placed
with the line centers at increasing 1-unit increments. If offset is
defined and is a scalar, the first row is placed at the offset, and
subsequent rows are placed at increasing 1-unit increments. If offset
is an array, it must be a 1D array of the same length as the second
dimension of x. In this case each element in offset determines the
center of the corresponding row in the plot.

How about letting offset be either: a) a scalar, determining the
offset of all rows equally; or b) an array, determining the offset of
each row individually.

Because people are almost never going to want to have all the lines
stacked right on top of each other. The plot would be indecipherable
that way. The defaults are chosen to handle the most common use-cases
most easily.

In fact, why plot each row at integer y
coordinates? Could we allow for an optional y-coordinate array, each
element of which would be the y-coordinate at which to plot a row of
lines. Then you wouldn't need offset.

That is exactly what offset does if you pass an array.

If this is going to be used to implement rug plots, it would need some
way to handle columns of horizontal lines in addition to rows of
vertical lines. I see two ways to implement this. First is to have
to plot types, perhaps HEventRaster and VEventRaster. The first would
be as described above, while the second would be similar but
everything rotated 90 degrees. Another possibility is to change the
call signature to this:

EventRaster(x, y=None, offset=0, height=1, **kargs)

I think accepting an 'orientation' kwarg, which can take either
'horizontal' or 'vertical', determining the orientation of the lines
and reversing the roles of the x and y arrays.

That would work as well. Probably cleaner that way

The function will return a list of a new collection type I am
tentatively calling EventCollection. My thinking would be this would
be a subclass of a new collection type called GenericLineCollection,
which the current LineCollection would also subclass. They would
share things like the color handling and segment handling, however the
segment handling will be a "private" method that LineCollection will
have a public wrapper for. On the other hand methods to set or add
segments will remain private in EventCollection, although there will
be a method to return the segments if an artist really wants to
manipulate individual segments.

Why can't we just use LineCollection? I don't see a good reason to
create a new collection class here; the plot is simple.

Explained below.

The reason for doing it this way is that manipulating individual rows
of events should be very common, such as changing their position,
color, marker, width, and so on. On the other hand manipulating lines
individually should not be as common, although still supported.

Fair enough, then maybe a better idea is to create your own
EventRaster class (note camel case) to hold all the relevant data in
arrays. Then make a 'construct_raster' method could return a
LineCollection. Then again, weren't you passing extra kwargs to
'plot'? This approach would surely use ax.add_lines or
ax.add_linecollection something (I can't remember what it's called).

The whole point of creating a new collection type is that artists will
be able to manipulate individual sets of events.

For example, with an ordinary LineCollection it will be extremely
difficult to change the marker type, since doing so will change the
marker for all 3 points on each segment rather than just the middle
point. So if someone makes the plot, than wants to set rows to have
different marker types instead of being lines, they can do that if we
use a new collection class. But if we use LineCollection this becomes
much more difficult.

Similarly, with a LineCollection the lines lose their status as
objects with a single distinct position. They become objects with 3
2D coordinates. So if someone wants to add more events to the end,
they need to take care of handling the x and y coordinates, making
sure the x coordinates are the same and taking the y coordinates from
one of the existing lines. Similarly changing the height or vertical
position of all the objects is complicated, having to manually
calculate and modify the y coordinates of each point in each segment.

Again, the idea here is to make the most common use-cases as easy as
possible. LineCollection objects aren't really suited to the sort of
artistic changes that are typical with this sort of plot.

In fact I would say that having a separate collection class is central
to this idea. If users aren't able to manipulate the set of events as
such after they create the plot, then there really isn't any advantage
over just using a vlines plot. Calculating the ymin and ymax is one
line of code each, it is the artistic changes that save many lines of
code and a lot of complexity.

I would also like to add that the new collection object would be
useful outside of this plot type.

For example if someone wanted to create a rug plot as Nathaniel
described, and they want those along the same axes as the main plot,
then they would most likely not be be using the plot function, but
rather creating two individual collection objects in an existing
figure.

I can imagine other cases besides a strict rug plot where adding such
a collection object could be useful.

Absolutely. I think the next step, once you have an implementation, would be to submit a pull request and we can all help with a review.

(BTW -- feel free to submit pull requests at any point in a release cycle -- we have both a master and a maintenance branch, so we can work on new stuff and stable stuff at the same time).

Mike

···

On 11/11/2012 11:51 PM, Todd wrote:

On Thu, Sep 27, 2012 at 8:18 PM, Todd <toddrjen@...149...> wrote:

On Thu, Sep 27, 2012 at 1:44 PM, Todd <toddrjen@...149...> wrote:

On Thu, Sep 27, 2012 at 1:12 PM, Damon McDougall >>> <damon.mcdougall@...149...> wrote:

Hi Todd,

Firstly, thanks for taking the time to crystallise your thoughts in
words first. This is one of my bad habits; I tend to rush into things.

I have some feedback for you, hopefully we can all work together to
get this right. It's difficult when something new gets implemented and
someone expects it to do something and the only way to resolve it is
to break the calling API.

Where is API broken?

Anyway, I hope you'll find my comments
helpful at the least. I also encourage others to weigh in with
opinions and ideas.

Okay, I will discuss the rationale. I will snip out anything you
agree on for brevity.

Assuming we go with the name, here is my proposed call signature:

EventRaster(x, offset=0, height=1, **kargs)

CamelCase is discouraged for method names. Perhaps 'eventraster'?

Fair enough.

Also, we could also let **kwargs swallow the 'offset' and 'height'
keyword arguments. Then the user isn't constrained by which order to
put them in. The downside of this approach is that introspection is
more difficult.

I don't understand the advantage of this approach. If you use keyword
arguments, then the order doesn't matter. So with the approach above
you can use keyword arguments, in which case you can use whatever
order they want, or you can use positional arguments. On the other
hand putting it in **kwargs, we lose the ability to use positional
arguments. So we lose nothing by allowing both positional and keyword
arguments. It is also easier to implement.

offset determines the positions of the rows. By default, the first
row is placed with the line center y=0, and subsequent rows are placed
with the line centers at increasing 1-unit increments. If offset is
defined and is a scalar, the first row is placed at the offset, and
subsequent rows are placed at increasing 1-unit increments. If offset
is an array, it must be a 1D array of the same length as the second
dimension of x. In this case each element in offset determines the
center of the corresponding row in the plot.

How about letting offset be either: a) a scalar, determining the
offset of all rows equally; or b) an array, determining the offset of
each row individually.

Because people are almost never going to want to have all the lines
stacked right on top of each other. The plot would be indecipherable
that way. The defaults are chosen to handle the most common use-cases
most easily.

In fact, why plot each row at integer y
coordinates? Could we allow for an optional y-coordinate array, each
element of which would be the y-coordinate at which to plot a row of
lines. Then you wouldn't need offset.

That is exactly what offset does if you pass an array.

If this is going to be used to implement rug plots, it would need some
way to handle columns of horizontal lines in addition to rows of
vertical lines. I see two ways to implement this. First is to have
to plot types, perhaps HEventRaster and VEventRaster. The first would
be as described above, while the second would be similar but
everything rotated 90 degrees. Another possibility is to change the
call signature to this:

EventRaster(x, y=None, offset=0, height=1, **kargs)

I think accepting an 'orientation' kwarg, which can take either
'horizontal' or 'vertical', determining the orientation of the lines
and reversing the roles of the x and y arrays.

That would work as well. Probably cleaner that way

The function will return a list of a new collection type I am
tentatively calling EventCollection. My thinking would be this would
be a subclass of a new collection type called GenericLineCollection,
which the current LineCollection would also subclass. They would
share things like the color handling and segment handling, however the
segment handling will be a "private" method that LineCollection will
have a public wrapper for. On the other hand methods to set or add
segments will remain private in EventCollection, although there will
be a method to return the segments if an artist really wants to
manipulate individual segments.

Why can't we just use LineCollection? I don't see a good reason to
create a new collection class here; the plot is simple.

Explained below.

The reason for doing it this way is that manipulating individual rows
of events should be very common, such as changing their position,
color, marker, width, and so on. On the other hand manipulating lines
individually should not be as common, although still supported.

Fair enough, then maybe a better idea is to create your own
EventRaster class (note camel case) to hold all the relevant data in
arrays. Then make a 'construct_raster' method could return a
LineCollection. Then again, weren't you passing extra kwargs to
'plot'? This approach would surely use ax.add_lines or
ax.add_linecollection something (I can't remember what it's called).

The whole point of creating a new collection type is that artists will
be able to manipulate individual sets of events.

For example, with an ordinary LineCollection it will be extremely
difficult to change the marker type, since doing so will change the
marker for all 3 points on each segment rather than just the middle
point. So if someone makes the plot, than wants to set rows to have
different marker types instead of being lines, they can do that if we
use a new collection class. But if we use LineCollection this becomes
much more difficult.

Similarly, with a LineCollection the lines lose their status as
objects with a single distinct position. They become objects with 3
2D coordinates. So if someone wants to add more events to the end,
they need to take care of handling the x and y coordinates, making
sure the x coordinates are the same and taking the y coordinates from
one of the existing lines. Similarly changing the height or vertical
position of all the objects is complicated, having to manually
calculate and modify the y coordinates of each point in each segment.

Again, the idea here is to make the most common use-cases as easy as
possible. LineCollection objects aren't really suited to the sort of
artistic changes that are typical with this sort of plot.

In fact I would say that having a separate collection class is central
to this idea. If users aren't able to manipulate the set of events as
such after they create the plot, then there really isn't any advantage
over just using a vlines plot. Calculating the ymin and ymax is one
line of code each, it is the artistic changes that save many lines of
code and a lot of complexity.

I would also like to add that the new collection object would be
useful outside of this plot type.

For example if someone wanted to create a rug plot as Nathaniel
described, and they want those along the same axes as the main plot,
then they would most likely not be be using the plot function, but
rather creating two individual collection objects in an existing
figure.

I can imagine other cases besides a strict rug plot where adding such
a collection object could be useful.

Now that 1.2 is out, can we revisit this? I would like to get it
implemented for the next feature release.

This hasn't been mentioned yet, but Todd will hopefully find our
developer docs useful:
http://matplotlib.org/devel/index.html

In particular, there's a section on writing a new pyplot function:
http://matplotlib.org/devel/coding_guide.html#writing-a-new-pyplot-function

···

On Mon, Nov 12, 2012 at 7:36 AM, Michael Droettboom <mdroe@...31...> wrote:

On 11/11/2012 11:51 PM, Todd wrote:

Now that 1.2 is out, can we revisit this? I would like to get it
implemented for the next feature release.

Absolutely. I think the next step, once you have an implementation,
would be to submit a pull request and we can all help with a review.

--
Paul Ivanov
314 address only used for lists, off-list direct email at:
http://pirsquared.org | GPG/PGP key id: 0x0F3E28F7

Thanks for that, Paul.

Todd, there's also a section on writing tests for matplotlib on the
page Paul pointed out. For a new feature there should be a couple of
tests to go with it to make sure everything passes sanity checks.

Thanks for spending your time contributing!

···

On Mon, Nov 12, 2012 at 2:17 PM, Paul Ivanov <pivanov314@...149...> wrote:

On Mon, Nov 12, 2012 at 7:36 AM, Michael Droettboom <mdroe@...31...> wrote:

On 11/11/2012 11:51 PM, Todd wrote:

Now that 1.2 is out, can we revisit this? I would like to get it
implemented for the next feature release.

Absolutely. I think the next step, once you have an implementation,
would be to submit a pull request and we can all help with a review.

This hasn't been mentioned yet, but Todd will hopefully find our
developer docs useful:
http://matplotlib.org/devel/index.html

In particular, there's a section on writing a new pyplot function:
http://matplotlib.org/devel/coding_guide.html#writing-a-new-pyplot-function

--
Damon McDougall
http://www.damon-is-a-geek.com
Institute for Computational Engineering Sciences
201 E. 24th St.
Stop C0200
The University of Texas at Austin
Austin, TX 78712-1229

I have completed the plot type, including unit tests and examples (I am not
an artist so someone else can probably make the examples prettier). I've
confirmed pep8 compliance and run the code through pyflakes and pylint in
addition to the unit tests.

It is divided into two parts: an EventCollection class, which is a subclass
of LineCollection in collections.py, and an eventplot method in axes.py
(and pyplot, through boilerplate.py) which returns a list of
EventCollection objects.

I am ready to submit a git pull request now. However, it depends on
another git pull request I submitted, titled "add get_segments method to
collections.LineCollection<https://github.com/matplotlib/matplotlib/pull/1655>".
I can confirm the changes in this pull request work properly, I have been
using the new method extensively in my new plot type.

Would it be possible to get this accepted so I can submit the new plot type
for review? I am sure there will be lots of changes and cleanups that will
be required before the new plots can be accepted, while the get_segments
method is a relatively minor and non-intrusive change.

If you wish to look at the code before the pull request it is in the
toddrjen/matplotlib github fork, in the eventplot branch. The main changes
are to collections.py and axes.py. The tests are in test_axes.py and a new
test file test_collections.py. The examples are in eventcollection_demo.py
and eventplot_demo.py

Thanks a lot for your time.

···

On Mon, Nov 12, 2012 at 6:35 PM, Damon McDougall <damon.mcdougall@...149...>wrote:

On Mon, Nov 12, 2012 at 2:17 PM, Paul Ivanov <pivanov314@...149...> wrote:
> On Mon, Nov 12, 2012 at 7:36 AM, Michael Droettboom <mdroe@...31...> > wrote:
>> On 11/11/2012 11:51 PM, Todd wrote:
>>> Now that 1.2 is out, can we revisit this? I would like to get it
>>> implemented for the next feature release.
>>>
>>
>> Absolutely. I think the next step, once you have an implementation,
>> would be to submit a pull request and we can all help with a review.
>
> This hasn't been mentioned yet, but Todd will hopefully find our
> developer docs useful:
> http://matplotlib.org/devel/index.html
>
> In particular, there's a section on writing a new pyplot function:
>
http://matplotlib.org/devel/coding_guide.html#writing-a-new-pyplot-function

Thanks for that, Paul.

Todd, there's also a section on writing tests for matplotlib on the
page Paul pointed out. For a new feature there should be a couple of
tests to go with it to make sure everything passes sanity checks.

Thanks for spending your time contributing!

Thanks for getting get_segments in so quickly.

The pull request has been submitted, see "Add EventCollection and
eventplot<https://github.com/matplotlib/matplotlib/pull/1657>
"

···

On Mon, Jan 14, 2013 at 1:28 AM, Todd <toddrjen@...149...> wrote:

On Mon, Nov 12, 2012 at 6:35 PM, Damon McDougall < > damon.mcdougall@...149...> wrote:

On Mon, Nov 12, 2012 at 2:17 PM, Paul Ivanov <pivanov314@...149...> >> wrote:
> On Mon, Nov 12, 2012 at 7:36 AM, Michael Droettboom <mdroe@...31...> >> wrote:
>> On 11/11/2012 11:51 PM, Todd wrote:
>>> Now that 1.2 is out, can we revisit this? I would like to get it
>>> implemented for the next feature release.
>>>
>>
>> Absolutely. I think the next step, once you have an implementation,
>> would be to submit a pull request and we can all help with a review.
>
> This hasn't been mentioned yet, but Todd will hopefully find our
> developer docs useful:
> http://matplotlib.org/devel/index.html
>
> In particular, there's a section on writing a new pyplot function:
>
http://matplotlib.org/devel/coding_guide.html#writing-a-new-pyplot-function

Thanks for that, Paul.

Todd, there's also a section on writing tests for matplotlib on the
page Paul pointed out. For a new feature there should be a couple of
tests to go with it to make sure everything passes sanity checks.

Thanks for spending your time contributing!

I have completed the plot type, including unit tests and examples (I am
not an artist so someone else can probably make the examples prettier).
I've confirmed pep8 compliance and run the code through pyflakes and pylint
in addition to the unit tests.

It is divided into two parts: an EventCollection class, which is a
subclass of LineCollection in collections.py, and an eventplot method in
axes.py (and pyplot, through boilerplate.py) which returns a list of
EventCollection objects.

I am ready to submit a git pull request now. However, it depends on
another git pull request I submitted, titled "add get_segments method to
collections.LineCollection<https://github.com/matplotlib/matplotlib/pull/1655>".
I can confirm the changes in this pull request work properly, I have been
using the new method extensively in my new plot type.

Would it be possible to get this accepted so I can submit the new plot
type for review? I am sure there will be lots of changes and cleanups that
will be required before the new plots can be accepted, while the
get_segments method is a relatively minor and non-intrusive change.

If you wish to look at the code before the pull request it is in the
toddrjen/matplotlib github fork, in the eventplot branch. The main changes
are to collections.py and axes.py. The tests are in test_axes.py and a new
test file test_collections.py. The examples are in eventcollection_demo.py
and eventplot_demo.py

Thanks a lot for your time.