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

Skip to content

Commit d68662a

Browse files
committed
add *bottom* keyword parameter for stem command and implement legend handler for stem
1 parent 018d533 commit d68662a

File tree

6 files changed

+147
-32
lines changed

6 files changed

+147
-32
lines changed

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
2011-06-16 Added *bottom* keyword parameter for the stem command.
2+
Also, implemented a legend handler for the stem plot.
3+
- JJL
4+
15
2011-04-17 Disable keyboard auto-repeat in qt4 backend by ignoring
26
key events resulting from auto-repeat. This makes
37
constrained zoom/pan work. - EF
Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,31 @@
11
import matplotlib.pyplot as plt
22

3-
ax = plt.subplot(111)
4-
3+
ax = plt.subplot(311)
4+
55
b1 = ax.bar([0, 1, 2], [0.2, 0.3, 0.1], width=0.4,
66
label="Bar 1", align="center")
77

88
b2 = ax.bar([0.5, 1.5, 2.5], [0.3, 0.2, 0.2], color="red", width=0.4,
99
label="Bar 2", align="center")
1010

11+
ax.legend()
12+
13+
ax = plt.subplot(312)
14+
1115
err1 = ax.errorbar([0, 1, 2], [2, 3, 1], xerr=0.4, fmt="s",
1216
label="test 1")
1317
err2 = ax.errorbar([0, 1, 2], [3, 2, 4], yerr=0.3, fmt="o",
1418
label="test 2")
1519
err3 = ax.errorbar([0, 1, 2], [1, 1, 3], xerr=0.4, yerr=0.3, fmt="^",
1620
label="test 3")
1721

18-
# legend
19-
leg1 = plt.legend(loc=1)
22+
ax.legend()
23+
24+
ax = plt.subplot(313)
25+
26+
ll = ax.stem([0.3, 1.5, 2.7], [1, 3.6, 2.7], label="stem test")
27+
28+
ax.legend()
2029

2130
plt.show()
22-
31+

lib/matplotlib/axes.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import matplotlib.transforms as mtransforms
3535
import matplotlib.tri as mtri
3636

37-
from matplotlib.container import BarContainer, ErrorbarContainer
37+
from matplotlib.container import BarContainer, ErrorbarContainer, StemContainer
3838

3939
iterable = cbook.iterable
4040
is_string_like = cbook.is_string_like
@@ -4874,7 +4874,8 @@ def broken_barh(self, xranges, yrange, **kwargs):
48744874

48754875
return col
48764876

4877-
def stem(self, x, y, linefmt='b-', markerfmt='bo', basefmt='r-'):
4877+
def stem(self, x, y, linefmt='b-', markerfmt='bo', basefmt='r-',
4878+
bottom=None, label=None):
48784879
"""
48794880
call signature::
48804881
@@ -4903,18 +4904,27 @@ def stem(self, x, y, linefmt='b-', markerfmt='bo', basefmt='r-'):
49034904
if not self._hold: self.cla()
49044905
self.hold(True)
49054906

4906-
markerline, = self.plot(x, y, markerfmt)
4907+
markerline, = self.plot(x, y, markerfmt, label="_nolegend_")
4908+
4909+
if bottom is None:
4910+
bottom = 0
49074911

49084912
stemlines = []
49094913
for thisx, thisy in zip(x, y):
4910-
l, = self.plot([thisx,thisx], [0, thisy], linefmt)
4914+
l, = self.plot([thisx,thisx], [bottom, thisy], linefmt,
4915+
label="_nolegend_")
49114916
stemlines.append(l)
49124917

4913-
baseline, = self.plot([np.amin(x), np.amax(x)], [0,0], basefmt)
4918+
baseline, = self.plot([np.amin(x), np.amax(x)], [bottom,bottom],
4919+
basefmt, label="_nolegend_")
49144920

49154921
self.hold(remember_hold)
49164922

4917-
return markerline, stemlines, baseline
4923+
stem_container = StemContainer((markerline, stemlines, baseline),
4924+
label=label)
4925+
self.add_container(stem_container)
4926+
4927+
return stem_container
49184928

49194929

49204930
def pie(self, x, explode=None, labels=None, colors=None,

lib/matplotlib/container.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,13 @@ def __init__(self, lines, has_xerr=False, has_yerr=False, **kwargs):
101101
Container.__init__(self, lines, **kwargs)
102102

103103

104+
class StemContainer(Container):
105+
106+
def __init__(self, markerline_stemlines_baseline, **kwargs):
107+
markerline, stemlines, baseline = markerline_stemlines_baseline
108+
self.markerline = markerline
109+
self.stemlines = stemlines
110+
self.baseline = baseline
111+
Container.__init__(self, markerline_stemlines_baseline, **kwargs)
112+
113+

lib/matplotlib/legend.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""
22
The legend module defines the Legend class, which is responsible for
3-
drawing legends associated with axes and/or figures.
3+
drawing legends associated with axes and/or figures.
44
55
The Legend class can be considered as a container of legend handles
66
and legend texts. Creation of corresponding legend handles from the
@@ -28,7 +28,7 @@
2828

2929
from matplotlib.offsetbox import HPacker, VPacker, TextArea, DrawingArea, DraggableOffsetBox
3030

31-
from matplotlib.container import ErrorbarContainer, BarContainer
31+
from matplotlib.container import ErrorbarContainer, BarContainer, StemContainer
3232
import legend_handler
3333

3434

@@ -470,6 +470,7 @@ def _approx_text_height(self, renderer=None):
470470
# elements and the legend handlers.
471471

472472
_default_handler_map = {
473+
StemContainer:legend_handler.HandlerStem(),
473474
ErrorbarContainer:legend_handler.HandlerErrorbar(),
474475
Line2D:legend_handler.HandlerLine2D(),
475476
Patch:legend_handler.HandlerPatch(),
@@ -510,7 +511,7 @@ def get_legend_handler_map(self):
510511
"""
511512

512513
default_handler_map = self.get_default_handler_map()
513-
514+
514515
if self._handler_map:
515516
hm = default_handler_map.copy()
516517
hm.update(self._handler_map)

lib/matplotlib/legend_handler.py

Lines changed: 99 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
This module defines default legend handlers.
2+
This module defines default legend handlers.
33
44
Legend handlers are expected to be a callable object with a following
55
signature. ::
@@ -124,14 +124,12 @@ def create_artists(self, legend, orig_handle,
124124
raise NotImplementedError('Derived must override')
125125

126126

127-
class HandlerLine2D(HandlerBase):
128-
"""
129-
Handler for Line2D instances
130-
"""
127+
class HandlerNpoints(HandlerBase):
131128
def __init__(self, marker_pad=0.3, numpoints=None, **kw):
132129
HandlerBase.__init__(self, **kw)
133-
self._marker_pad = marker_pad
130+
134131
self._numpoints = numpoints
132+
self._marker_pad = marker_pad
135133

136134
def get_numpoints(self, legend):
137135
if self._numpoints is None:
@@ -157,6 +155,31 @@ def get_xdata(self, legend, xdescent, ydescent, width, height, fontsize):
157155

158156

159157

158+
class HandlerNpointsYoffsets(HandlerNpoints):
159+
def __init__(self, numpoints=None, yoffsets=None, **kw):
160+
HandlerNpoints.__init__(self,numpoints=numpoints, **kw)
161+
self._yoffsets = yoffsets
162+
163+
def get_ydata(self, legend, xdescent, ydescent, width, height, fontsize):
164+
if self._yoffsets is None:
165+
ydata = height*legend._scatteryoffsets
166+
else:
167+
ydata = height*np.asarray(self._yoffsets)
168+
169+
return ydata
170+
171+
172+
173+
174+
175+
class HandlerLine2D(HandlerNpoints):
176+
"""
177+
Handler for Line2D instances
178+
"""
179+
def __init__(self, marker_pad=0.3, numpoints=None, **kw):
180+
HandlerNpoints.__init__(self, marker_pad=marker_pad, numpoints=numpoints, **kw)
181+
182+
160183
def create_artists(self, legend, orig_handle,
161184
xdescent, ydescent, width, height, fontsize,
162185
trans):
@@ -263,14 +286,13 @@ def create_artists(self, legend, orig_handle,
263286

264287

265288

266-
class HandlerRegularPolyCollection(HandlerLine2D):
289+
class HandlerRegularPolyCollection(HandlerNpointsYoffsets):
267290
"""
268291
Handler for RegularPolyCollections.
269292
"""
270-
def __init__(self, scatteryoffsets=None, sizes=None, **kw):
271-
HandlerLine2D.__init__(self, **kw)
293+
def __init__(self, yoffsets=None, sizes=None, **kw):
294+
HandlerNpointsYoffsets.__init__(self, yoffsets=yoffsets, **kw)
272295

273-
self._scatteryoffsets = scatteryoffsets
274296
self._sizes = sizes
275297

276298
def get_numpoints(self, legend):
@@ -279,14 +301,6 @@ def get_numpoints(self, legend):
279301
else:
280302
return self._numpoints
281303

282-
def get_ydata(self, legend, xdescent, ydescent, width, height, fontsize):
283-
if self._scatteryoffsets is None:
284-
ydata = height*legend._scatteryoffsets
285-
else:
286-
ydata = height*np.asarray(self._scatteryoffsets)
287-
288-
return ydata
289-
290304
def get_sizes(self, legend, orig_handle,
291305
xdescent, ydescent, width, height, fontsize):
292306
if self._sizes is None:
@@ -467,6 +481,73 @@ def create_artists(self, legend, orig_handle,
467481

468482

469483

484+
class HandlerStem(HandlerNpointsYoffsets):
485+
"""
486+
Handler for Errorbars
487+
"""
488+
def __init__(self, marker_pad=0.3, numpoints=None,
489+
bottom=None, yoffsets=None, **kw):
490+
491+
HandlerNpointsYoffsets.__init__(self, marker_pad=marker_pad,
492+
numpoints=numpoints,
493+
yoffsets=yoffsets,
494+
**kw)
495+
496+
self._bottom = bottom
497+
498+
499+
def get_ydata(self, legend, xdescent, ydescent, width, height, fontsize):
500+
if self._yoffsets is None:
501+
ydata = height*(0.5*legend._scatteryoffsets + 0.5)
502+
else:
503+
ydata = height*np.asarray(self._yoffsets)
504+
505+
return ydata
506+
507+
508+
def create_artists(self, legend, orig_handle,
509+
xdescent, ydescent, width, height, fontsize,
510+
trans):
511+
512+
markerline, stemlines, baseline = orig_handle
513+
514+
xdata, xdata_marker = self.get_xdata(legend, xdescent, ydescent,
515+
width, height, fontsize)
516+
517+
ydata = self.get_ydata(legend, xdescent, ydescent,
518+
width, height, fontsize)
519+
520+
if self._bottom is None:
521+
bottom = 0.
522+
else:
523+
bottom = self._bottom
524+
525+
ax = markerline.axes
526+
#saved_dict = self.pre_plot_commands(ax)
527+
528+
leg_markerline = Line2D(xdata_marker, ydata[:len(xdata_marker)])
529+
self.update_prop(leg_markerline, markerline, legend)
530+
531+
leg_stemlines = []
532+
for thisx, thisy in zip(xdata_marker, ydata):
533+
l = Line2D([thisx,thisx], [bottom, thisy])
534+
leg_stemlines.append(l)
535+
536+
for lm, m in zip(leg_stemlines, stemlines):
537+
self.update_prop(lm, m, legend)
538+
539+
leg_baseline = Line2D([np.amin(xdata), np.amax(xdata)],
540+
[bottom, bottom])
541+
542+
self.update_prop(leg_baseline, baseline, legend)
543+
544+
artists = [leg_markerline]
545+
artists.extend(leg_stemlines)
546+
artists.append(leg_baseline)
547+
548+
return artists
549+
550+
470551
class HandlerTuple(HandlerBase):
471552
"""
472553
Handler for Tuple

0 commit comments

Comments
 (0)