Skip to content

Commit 8072b7d

Browse files
committed
add eventplot method to axes class
1 parent f7e9174 commit 8072b7d

File tree

1 file changed

+169
-0
lines changed

1 file changed

+169
-0
lines changed

lib/matplotlib/axes.py

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3812,6 +3812,175 @@ def vlines(self, x, ymin, ymax, colors='k', linestyles='solid',
38123812

38133813
return coll
38143814

3815+
@docstring.dedent_interpd
3816+
def eventplot(self, positions, orientation='horizontal', lineoffsets=1,
3817+
linelengths=1, linewidths=None, colors=None,
3818+
linestyles='solid', **kwargs):
3819+
"""
3820+
Plot identical parallel lines at specific positions.
3821+
3822+
Call signature::
3823+
3824+
eventplot(positions, orientation='horizontal', lineoffsets=0,
3825+
linelengths=1, linewidths=None, color =None,
3826+
linestyles='solid'
3827+
3828+
Plot parallel lines at the given positions. positions should be a 1D
3829+
or 2D array-like object, with each row corresponding to a row or column
3830+
of lines.
3831+
3832+
This type of plot is commonly used in neuroscience for representing
3833+
neural events, where it is commonly called a spike raster, dot raster,
3834+
or raster plot.
3835+
3836+
However, it is useful in any situation where you wish to show the
3837+
timing or position of multiple sets of discrete events, such as the
3838+
arrival times of people to a business on each day of the month or the
3839+
date of hurricanes each year of the last century.
3840+
3841+
*orientation* : [ 'horizonal' | 'vertical' ]
3842+
'horizonal' : the lines will be vertical and arranged in rows
3843+
"vertical' : lines will be horizontal and arranged in columns
3844+
3845+
*lineoffsets* :
3846+
A float or array-like containing floats.
3847+
3848+
*linelengths* :
3849+
A float or array-like containing floats.
3850+
3851+
*linewidths* :
3852+
A float or array-like containing floats.
3853+
3854+
*colors*
3855+
must be a sequence of RGBA tuples (eg arbitrary color
3856+
strings, etc, not allowed) or a list of such sequences
3857+
3858+
*linestyles* :
3859+
[ 'solid' | 'dashed' | 'dashdot' | 'dotted' ] or an array of these
3860+
values
3861+
3862+
For linelengths, linewidths, colors, and linestyles, if only a single
3863+
value is given, that value is applied to all lines. If an array-like
3864+
is given, it must have the same length as positions, and each value
3865+
will be applied to the corresponding row or column in positions.
3866+
3867+
Returns a list of :class:`matplotlib.collections.EventCollection`
3868+
objects that were added.
3869+
3870+
kwargs are :class:`~matplotlib.collections.LineCollection` properties:
3871+
3872+
%(LineCollection)s
3873+
3874+
**Example:**
3875+
3876+
.. plot:: mpl_examples/pylab_examples/eventplot_demo.py
3877+
"""
3878+
self._process_unit_info(xdata=positions,
3879+
ydata=[lineoffsets, linelengths],
3880+
kwargs=kwargs)
3881+
3882+
# We do the conversion first since not all unitized data is uniform
3883+
positions = self.convert_xunits(positions)
3884+
lineoffsets = self.convert_yunits(lineoffsets)
3885+
linelengths = self.convert_yunits(linelengths)
3886+
3887+
if not iterable(positions):
3888+
positions = [positions]
3889+
elif any(iterable(position) for position in positions):
3890+
positions = [np.asanyarray(position) for position in positions]
3891+
else:
3892+
positions = [np.asanyarray(positions)]
3893+
3894+
if len(positions) == 0:
3895+
return []
3896+
3897+
if not iterable(lineoffsets):
3898+
lineoffsets = [lineoffsets]
3899+
if not iterable(linelengths):
3900+
linelengths = [linelengths]
3901+
if not iterable(linewidths):
3902+
linewidths = [linewidths]
3903+
if not iterable(colors):
3904+
colors = [colors]
3905+
if hasattr(linestyles, 'lower') or not iterable(linestyles):
3906+
linestyles = [linestyles]
3907+
3908+
lineoffsets = np.asarray(lineoffsets)
3909+
linelengths = np.asarray(linelengths)
3910+
linewidths = np.asarray(linewidths)
3911+
3912+
if len(lineoffsets) == 0:
3913+
lineoffsets = [None]
3914+
if len(linelengths) == 0:
3915+
linelengths = [None]
3916+
if len(linewidths) == 0:
3917+
lineoffsets = [None]
3918+
if len(linewidths) == 0:
3919+
lineoffsets = [None]
3920+
if len(colors) == 0:
3921+
colors = [None]
3922+
3923+
if len(lineoffsets) == 1:
3924+
lineoffsets = np.tile(lineoffsets, len(positions))
3925+
lineoffsets[0] = 0
3926+
lineoffsets = np.cumsum(lineoffsets)
3927+
if len(linelengths) == 1:
3928+
linelengths = np.tile(linelengths, len(positions))
3929+
if len(linewidths) == 1:
3930+
linewidths = np.tile(linewidths, len(positions))
3931+
if len(colors) == 1:
3932+
colors = np.asanyarray(colors)
3933+
colors = np.tile(colors, [len(positions), 1])
3934+
if len(linestyles) == 1:
3935+
linestyles = [linestyles] * len(positions)
3936+
3937+
if len(lineoffsets) != len(positions):
3938+
raise ValueError('lineoffsets and positions are unequal sized \
3939+
sequences')
3940+
if len(linelengths) != len(positions):
3941+
raise ValueError('linelengths and positions are unequal sized \
3942+
sequences')
3943+
if len(linewidths) != len(positions):
3944+
raise ValueError('linewidths and positions are unequal sized \
3945+
sequences')
3946+
if len(colors) != len(positions):
3947+
raise ValueError('colors and positions are unequal sized \
3948+
sequences')
3949+
if len(linestyles) != len(positions):
3950+
raise ValueError('linestyles and positions are unequal sized \
3951+
sequences')
3952+
3953+
colls = []
3954+
for position, lineoffset, linelength, linewidth, color, linestyle in \
3955+
itertools.izip(positions, lineoffsets, linelengths, linewidths,
3956+
colors, linestyles):
3957+
coll = mcoll.EventCollection(position,
3958+
orientation=orientation,
3959+
lineoffset=lineoffset,
3960+
linelength=linelength,
3961+
linewidth=linewidth,
3962+
color=color,
3963+
linestyle=linestyle)
3964+
self.add_collection(coll)
3965+
coll.update(kwargs)
3966+
colls.append(coll)
3967+
3968+
if len(positions) > 0:
3969+
minpos = min(position.min() for position in positions)
3970+
maxpos = max(position.max() for position in positions)
3971+
3972+
minline = (lineoffsets - linelengths).min()
3973+
maxline = (lineoffsets + linelengths).max()
3974+
3975+
if colls[0].is_horizontal():
3976+
corners = (minpos, minline), (maxpos, maxline)
3977+
else:
3978+
corners = (minline, minpos), (maxline, maxpos)
3979+
self.update_datalim(corners)
3980+
self.autoscale_view()
3981+
3982+
return colls
3983+
38153984
#### Basic plotting
38163985
@docstring.dedent_interpd
38173986
def plot(self, *args, **kwargs):

0 commit comments

Comments
 (0)