Skip to content

Added feature for specifying uniform handle sizes for scatter plost. #4257

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion lib/matplotlib/axes/_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,19 @@ def legend(self, *args, **kwargs):
else:
raise TypeError('Invalid arguments to legend.')

self.legend_ = mlegend.Legend(self, handles, labels, **kwargs)
# If uniform_size is specified, verify that there's no conflicting
# parameters.
if 'uniform_size' in kwargs:
if 'markerscale' in kwargs or 'handler_map' in kwargs:
raise TypeError("Cannot specify 'markerscale' or " +
"'handler_map' to legend when " +
"'uniform_size' is specified.")
uniform_size = kwargs.pop('uniform_size')
self.legend_ = mlegend.UniformLegend(self, handles, labels,
uniform_size, **kwargs)
else:
self.legend_ = mlegend.Legend(self, handles, labels, **kwargs)

self.legend_._remove_method = lambda h: setattr(self, 'legend_', None)
return self.legend_

Expand Down
17 changes: 16 additions & 1 deletion lib/matplotlib/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
from matplotlib.axes import Axes, SubplotBase, subplot_class_factory
from matplotlib.blocking_input import BlockingMouseInput, BlockingKeyMouseInput
from matplotlib.legend import Legend
from matplotlib.legend import UniformLegend
from matplotlib.patches import Rectangle
from matplotlib.projections import (get_projection_names,
process_projection_requirements)
Expand Down Expand Up @@ -1222,7 +1223,21 @@ def legend(self, handles, labels, *args, **kwargs):

.. plot:: mpl_examples/pylab_examples/figlegend_demo.py
"""
l = Legend(self, handles, labels, *args, **kwargs)

# If uniform_size is specified, verify that there's no conflicting
# parameters.
l = None
if 'uniform_size' in kwargs:
if 'markerscale' in kwargs or 'handler_map' in kwargs:
raise TypeError("Cannot specify 'markerscale' or " +
"'handler_map' to legend when " +
"'uniform_size' is specified.")
uniform_size = kwargs.pop('uniform_size')
l = UniformLegend(self, handles, labels, uniform_size, *args,
**kwargs)
else:
l = Legend(self, handles, labels, *args, **kwargs)

self.legends.append(l)
l._remove_method = lambda h: self.legends.remove(h)
return l
Expand Down
90 changes: 90 additions & 0 deletions lib/matplotlib/legend.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -993,3 +993,93 @@ def draggable(self, state=None, use_blit=False, update="loc"):
self._draggable = None

return self._draggable


class UniformLegend(Legend):
def __str__(self):
return "uniformLegend"

def __init__(self, parent, handles, labels, uniform_size,
loc=None,
numpoints=None, # the number of points in the legend line
markerfirst=True, # controls ordering (left-to-right) of
# legend marker and label
scatterpoints=None, # number of scatter points
scatteryoffsets=None,
prop=None, # properties for the legend texts
fontsize=None, # keyword to set font size directly

# spacing & pad defined as a fraction of the font-size
borderpad=None, # the whitespace inside the legend border
labelspacing=None, # the vertical space between the legend
# entries
handlelength=None, # the length of the legend handles
handleheight=None, # the height of the legend handles
handletextpad=None, # the pad between the legend handle
# and text
borderaxespad=None, # the pad between the axes and legend
# border
columnspacing=None, # spacing between columns

ncol=1, # number of columns
mode=None, # mode for horizontal distribution of columns.
# None, "expand"

fancybox=None, # True use a fancy box, false use a rounded
# box, none use rc
shadow=None,
title=None, # set a title for the legend

framealpha=None, # set frame alpha

bbox_to_anchor=None, # bbox that the legend will be anchored.
bbox_transform=None, # transform for the bbox
frameon=None
):
uniformHandlerMap = {
StemContainer:
legend_handler.HandlerUniformStem(uniform_size=uniform_size),
ErrorbarContainer:
legend_handler.HandlerUniformErrorBar(uniform_size=uniform_size),
Line2D:
legend_handler.HandlerUniformLine2D(uniform_size=uniform_size),
PathCollection:
legend_handler.HandlerPathCollection(sizes=[uniform_size]*3),
RegularPolyCollection:
legend_handler.HandlerRegularPolyCollection(
sizes=[uniform_size]*3),
CircleCollection:
legend_handler.HandlerCircleCollection(sizes=[uniform_size]*3),
}

# Consult Legend.__init__ for purpose of each parameter.
Legend.__init__(self, parent, handles, labels,
loc=loc,
numpoints=numpoints,
# markerscale does nothing when using uniform sizing.
markerscale=None,
markerfirst=markerfirst,
scatterpoints=scatterpoints,
scatteryoffsets=scatteryoffsets,
prop=prop,
fontsize=fontsize,
borderpad=borderpad,
labelspacing=labelspacing,
handlelength=handlelength,
handleheight=handleheight,
handletextpad=handletextpad,
borderaxespad=borderaxespad,
columnspacing=columnspacing,
ncol=1,
mode=mode,
fancybox=fancybox,
shadow=shadow,
title=title,
framealpha=framealpha,
bbox_to_anchor=bbox_to_anchor,
bbox_transform=bbox_transform,
frameon=frameon,
# Override with custom handler map that forces uniform
# sizing.
handler_map=uniformHandlerMap,
)
57 changes: 57 additions & 0 deletions lib/matplotlib/legend_handler.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -617,3 +617,60 @@ def create_artists(self, legend, orig_handle,
self.update_prop(p, orig_handle, legend)
p.set_transform(trans)
return [p]


class HandlerUniformLine2D(HandlerLine2D):
"""
Handler for Uniform sized Line2D instances
"""

def __init__(self, uniform_size, **kw):
self._uniform_size = uniform_size
HandlerLine2D.__init__(self, **kw)

def create_artists(self, legend, orig_handle,
xdescent, ydescent, width, height, fontsize,
trans):
artists = HandlerLine2D.create_artists(self, legend, orig_handle,
xdescent, ydescent,
width, height,
fontsize, trans)
artists[-1].set_markersize(self._uniform_size)
return artists


class HandlerUniformErrorBar(HandlerErrorbar):
"""
Handler for Uniform sized Error instances
"""

def __init__(self, uniform_size, **kw):
self._uniform_size = uniform_size
HandlerErrorbar.__init__(self, **kw)

def create_artists(self, legend, orig_handle,
xdescent, ydescent, width, height, fontsize,
trans):
artists = HandlerErrorbar.create_artists(self, legend, orig_handle,
xdescent, ydescent,
width, height,
fontsize, trans)
artists[-1].set_markersize(self._uniform_size)
return artists


class HandlerUniformStem(HandlerStem):
def __init__(self, uniform_size, **kw):

HandlerStem.__init__(self, **kw)
self._uniform_size = uniform_size

def create_artists(self, legend, orig_handle,
xdescent, ydescent, width, height, fontsize,
trans):
artists = HandlerStem.create_artists(self, legend, orig_handle,
xdescent, ydescent,
width, height,
fontsize, trans)
artists[0].set_markersize(self._uniform_size)
return artists