Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 93cbcb3

Browse files
committed
Merge pull request matplotlib#1669 from toddrjen/eventplot
Add EventCollection and eventplot
2 parents ac957b2 + 1d51b6b commit 93cbcb3

File tree

53 files changed

+16080
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+16080
-0
lines changed

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
2013-01-23 Add 'savefig.directory' to rcParams to remember and fill in the last
22
directory saved to for figure save dialogs - Martin Spacek
33

4+
2013-01-13 Add eventplot method to axes and pyplot and EventCollection class
5+
to collections.
6+
47
2013-01-08 Added two extra titles to axes which are flush with the left and
58
right edges of the plot respectively.
69
Andrew Dawson

boilerplate.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ def boilerplate_gen():
108108
'contourf',
109109
'csd',
110110
'errorbar',
111+
'eventplot',
111112
'fill',
112113
'fill_between',
113114
'fill_betweenx',

doc/users/whats_new.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ revision, see the :ref:`github-stats`.
2222
new in matplotlib-1.3
2323
=====================
2424

25+
New eventplot plot type
26+
-------------------------------------
27+
Todd Jennings added a :func:`~matplotlib.pyplot.eventplot` function to
28+
create multiple rows or columns of identical line segments
29+
30+
New EventCollection collections class
31+
-------------------------------------
32+
Todd Jennings created the new :class:`~matplotlib.collections.EventCollection`
33+
class that allows for plotting and manipulating rows or columns of identical
34+
line segments
35+
2536
Baselines for stackplot
2637
-----------------------
2738
Till Stensitzki added non-zero baselines to :func:`~matplotlib.pyplot.stackplot`.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env python
2+
# -*- Coding:utf-8 -*-
3+
'''Plot two curves, then use EventCollections to mark the locations of the x
4+
and y data points on the respective axes for each curve'''
5+
6+
import matplotlib.pyplot as plt
7+
from matplotlib.collections import EventCollection
8+
import numpy as np
9+
10+
# create random data
11+
np.random.seed(50)
12+
xdata = np.random.random([2, 10])
13+
14+
# split the data into two parts
15+
xdata1 = xdata[0, :]
16+
xdata2 = xdata[1, :]
17+
18+
# sort the data so it makes clean curves
19+
xdata1.sort()
20+
xdata2.sort()
21+
22+
# create some y data points
23+
ydata1 = xdata1 ** 2
24+
ydata2 = 1 - xdata2 ** 3
25+
26+
# plot the data
27+
fig = plt.figure()
28+
ax = fig.add_subplot(1, 1, 1)
29+
ax.plot(xdata1, ydata1, 'r', xdata2, ydata2, 'b')
30+
31+
# create the events marking the x data points
32+
xevents1 = EventCollection(xdata1, color=[1, 0, 0], linelength=0.05)
33+
xevents2 = EventCollection(xdata2, color=[0, 0, 1], linelength=0.05)
34+
35+
# create the events marking the y data points
36+
yevents1 = EventCollection(ydata1, color=[1, 0, 0], linelength=0.05,
37+
orientation='vertical')
38+
yevents2 = EventCollection(ydata2, color=[0, 0, 1], linelength=0.05,
39+
orientation='vertical')
40+
41+
# add the events to the axis
42+
ax.add_collection(xevents1)
43+
ax.add_collection(xevents2)
44+
ax.add_collection(yevents1)
45+
ax.add_collection(yevents2)
46+
47+
# set the limits
48+
ax.set_xlim([0, 1])
49+
ax.set_ylim([0, 1])
50+
51+
ax.set_title('line plot with data points')
52+
53+
# display the plot
54+
plt.show()
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env python
2+
# -*- Coding:utf-8 -*-
3+
'''an eventplot showing sequences of events with various line properties
4+
the plot is shown in both horizontal and vertical orientations'''
5+
6+
import matplotlib.pyplot as plt
7+
import numpy as np
8+
9+
# set the random seed
10+
np.random.seed(0)
11+
12+
# create random data
13+
data1 = np.random.random([6, 50])
14+
15+
# set different colors for each set of positions
16+
colors1 = np.array([[1, 0, 0],
17+
[0, 1, 0],
18+
[0, 0, 1],
19+
[1, 1, 0],
20+
[1, 0, 1],
21+
[0, 1, 1]])
22+
23+
# set different line properties for each set of positions
24+
# note that some overlap
25+
lineoffsets1 = np.array([-15, -3, 1, 1.5, 6, 10])
26+
linelengths1 = [5, 2, 1, 1, 3, 1.5]
27+
28+
fig = plt.figure()
29+
30+
# create a horizontal plot
31+
ax1 = fig.add_subplot(221)
32+
ax1.eventplot(data1, colors=colors1, lineoffsets=lineoffsets1,
33+
linelengths=linelengths1)
34+
ax1.set_title('horizontal eventplot 1')
35+
36+
37+
# create a vertical plot
38+
ax2 = fig.add_subplot(223)
39+
ax2.eventplot(data1, colors=colors1, lineoffsets=lineoffsets1,
40+
linelengths=linelengths1, orientation='vertical')
41+
ax2.set_title('vertical eventplot 1')
42+
43+
# create another set of random data.
44+
# the gamma distribution is only used fo aesthetic purposes
45+
data2 = np.random.gamma(4, size=[60, 50])
46+
47+
# use individual values for the parameters this time
48+
# these values will be used for all data sets (except lineoffsets2, which
49+
# sets the increment between each data set in this usage)
50+
colors2 = [[0, 0, 0]]
51+
lineoffsets2 = 1
52+
linelengths2 = 1
53+
54+
# create a horizontal plot
55+
ax1 = fig.add_subplot(222)
56+
ax1.eventplot(data2, colors=colors2, lineoffsets=lineoffsets2,
57+
linelengths=linelengths2)
58+
ax1.set_title('horizontal eventplot 2')
59+
60+
61+
# create a vertical plot
62+
ax2 = fig.add_subplot(224)
63+
ax2.eventplot(data2, colors=colors2, lineoffsets=lineoffsets2,
64+
linelengths=linelengths2, orientation='vertical')
65+
ax2.set_title('vertical eventplot 2')
66+
67+
plt.show()

lib/matplotlib/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,7 @@ def tk_window_focus():
10891089
'matplotlib.tests.test_basic',
10901090
'matplotlib.tests.test_bbox_tight',
10911091
'matplotlib.tests.test_cbook',
1092+
'matplotlib.tests.test_collections',
10921093
'matplotlib.tests.test_colorbar',
10931094
'matplotlib.tests.test_colors',
10941095
'matplotlib.tests.test_contour',

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 and len(positions) != 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)