Skip to content

Add Spines class as a container for all Axes spines #17107

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

Merged
merged 2 commits into from
Dec 28, 2020
Merged
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
19 changes: 19 additions & 0 deletions doc/users/next_whats_new/2020-04-12-spines.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
``Axes.spines``
---------------

``Axes.spines`` is now a dedicated container class `.Spines` for a set of
`.Spine`\s instead of an ``OrderedDict``. On top of dict-like access,
``Axes.spines`` now also supports some ``pandas.Series``-like features.

Accessing single elements by item or by attribute

ax.spines['top'].set_visible(False)
ax.spines.top.set_visible(False)

Accessing a subset of items::

ax.spines[['top', 'right']].set_visible(False)

Accessing all items simultaneously::

ax.spines[:].set_visible(False)
3 changes: 1 addition & 2 deletions examples/axes_grid1/demo_axes_rgb.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ def demo_rgb2():

for ax in fig.axes:
ax.tick_params(axis='both', direction='in')
for sp1 in ax.spines.values():
sp1.set_color("w")
ax.spines[:].set_color("w")
for tick in ax.xaxis.get_major_ticks() + ax.yaxis.get_major_ticks():
tick.tick1line.set_markeredgecolor("w")
tick.tick2line.set_markeredgecolor("w")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,7 @@ def heatmap(data, row_labels, col_labels, ax=None,
rotation_mode="anchor")

# Turn spines off and create white grid.
for edge, spine in ax.spines.items():
spine.set_visible(False)
ax.spines[:].set_visible(False)

ax.set_xticks(np.arange(data.shape[1]+1)-.5, minor=True)
ax.set_yticks(np.arange(data.shape[0]+1)-.5, minor=True)
Expand Down
3 changes: 1 addition & 2 deletions examples/lines_bars_and_markers/linestyles.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ def plot_linestyles(ax, linestyles, title):
yticks=np.arange(len(linestyles)),
yticklabels=yticklabels)
ax.tick_params(left=False, bottom=False, labelbottom=False)
for spine in ax.spines.values():
spine.set_visible(False)
ax.spines[:].set_visible(False)

# For each line style, add a text annotation with a small offset from
# the reference point (0 in Axes coords, y tick value in Data coords).
Expand Down
3 changes: 1 addition & 2 deletions examples/lines_bars_and_markers/timeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@

# remove y axis and spines
ax.yaxis.set_visible(False)
for spine in ["left", "top", "right"]:
ax.spines[spine].set_visible(False)
ax.spines[["left", "top", "right"]].set_visible(False)

ax.margins(y=0.1)
plt.show()
Expand Down
5 changes: 1 addition & 4 deletions examples/showcase/bachelors_degrees_by_gender.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@
'#17becf', '#9edae5'])

# Remove the plot frame lines. They are unnecessary here.
ax.spines['top'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines[:].set_visible(False)

# Ensure that the axis ticks only show up on the bottom and left of the plot.
# Ticks on the right and top of the plot are generally unnecessary.
Expand Down
4 changes: 2 additions & 2 deletions examples/showcase/integral.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ def func(x):
fig.text(0.9, 0.05, '$x$')
fig.text(0.1, 0.9, '$y$')

ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines.right.set_visible(False)
ax.spines.top.set_visible(False)
ax.xaxis.set_ticks_position('bottom')

ax.set_xticks((a, b))
Expand Down
8 changes: 4 additions & 4 deletions examples/showcase/xkcd.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

fig = plt.figure()
ax = fig.add_axes((0.1, 0.2, 0.8, 0.7))
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines.right.set_color('none')
ax.spines.top.set_color('none')
ax.set_xticks([])
ax.set_yticks([])
ax.set_ylim([-30, 10])
Expand Down Expand Up @@ -47,8 +47,8 @@
fig = plt.figure()
ax = fig.add_axes((0.1, 0.2, 0.8, 0.7))
ax.bar([0, 1], [0, 100], 0.25)
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines.right.set_color('none')
ax.spines.top.set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.set_xticks([0, 1])
ax.set_xticklabels(['CONFIRMED BY\nEXPERIMENT', 'REFUTED BY\nEXPERIMENT'])
Expand Down
8 changes: 4 additions & 4 deletions examples/specialty_plots/skewt.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ class SkewXAxes(Axes):
def _init_axis(self):
# Taken from Axes and modified to use our modified X-axis
self.xaxis = SkewXAxis(self)
self.spines['top'].register_axis(self.xaxis)
self.spines['bottom'].register_axis(self.xaxis)
self.spines.top.register_axis(self.xaxis)
self.spines.bottom.register_axis(self.xaxis)
self.yaxis = maxis.YAxis(self)
self.spines['left'].register_axis(self.yaxis)
self.spines['right'].register_axis(self.yaxis)
self.spines.left.register_axis(self.yaxis)
self.spines.right.register_axis(self.yaxis)

def _gen_axes_spines(self):
spines = {'top': SkewSpine.linear_spine(self, 'top'),
Expand Down
4 changes: 2 additions & 2 deletions examples/subplots_axes_and_figures/broken_axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
ax2.set_ylim(0, .22) # most of the data

# hide the spines between ax and ax2
ax1.spines['bottom'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax1.spines.bottom.set_visible(False)
ax2.spines.top.set_visible(False)
ax1.xaxis.tick_top()
ax1.tick_params(labeltop=False) # don't put tick labels at the top
ax2.xaxis.tick_bottom()
Expand Down
6 changes: 2 additions & 4 deletions examples/ticks_and_spines/centered_spines_with_arrows.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@

fig, ax = plt.subplots()
# Move the left and bottom spines to x = 0 and y = 0, respectively.
ax.spines["left"].set_position(("data", 0))
ax.spines["bottom"].set_position(("data", 0))
ax.spines[["left", "bottom"]].set_position(("data", 0))
# Hide the top and right spines.
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.spines[["top", "right"]].set_visible(False)

# Draw arrows (as black triangles: ">k"/"^k") at the end of the axes. In each
# case, one of the coordinates (0) is a data coordinate (i.e., y = 0 or x = 0,
Expand Down
2 changes: 1 addition & 1 deletion examples/ticks_and_spines/multiple_yaxis_with_spines.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

# Offset the right spine of twin2. The ticks and label have already been
# placed on the right by twinx above.
twin2.spines["right"].set_position(("axes", 1.2))
twin2.spines.right.set_position(("axes", 1.2))

p1, = ax.plot([0, 1, 2], [0, 1, 2], "b-", label="Density")
p2, = twin1.plot([0, 1, 2], [0, 3, 2], "r-", label="Temperature")
Expand Down
32 changes: 16 additions & 16 deletions examples/ticks_and_spines/spine_placement_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,40 +21,40 @@
ax = fig.add_subplot(2, 2, 1)
ax.set_title('centered spines')
ax.plot(x, y)
ax.spines['left'].set_position('center')
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position('center')
ax.spines['top'].set_color('none')
ax.spines.left.set_position('center')
ax.spines.right.set_color('none')
ax.spines.bottom.set_position('center')
ax.spines.top.set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')

ax = fig.add_subplot(2, 2, 2)
ax.set_title('zeroed spines')
ax.plot(x, y)
ax.spines['left'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position('zero')
ax.spines['top'].set_color('none')
ax.spines.left.set_position('zero')
ax.spines.right.set_color('none')
ax.spines.bottom.set_position('zero')
ax.spines.top.set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')

ax = fig.add_subplot(2, 2, 3)
ax.set_title('spines at axes (0.6, 0.1)')
ax.plot(x, y)
ax.spines['left'].set_position(('axes', 0.6))
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position(('axes', 0.1))
ax.spines['top'].set_color('none')
ax.spines.left.set_position(('axes', 0.6))
ax.spines.right.set_color('none')
ax.spines.bottom.set_position(('axes', 0.1))
ax.spines.top.set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')

ax = fig.add_subplot(2, 2, 4)
ax.set_title('spines at data (1, 2)')
ax.plot(x, y)
ax.spines['left'].set_position(('data', 1))
ax.spines['right'].set_color('none')
ax.spines['bottom'].set_position(('data', 2))
ax.spines['top'].set_color('none')
ax.spines.left.set_position(('data', 1))
ax.spines.right.set_color('none')
ax.spines.bottom.set_position(('data', 2))
ax.spines.top.set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')

Expand Down
10 changes: 5 additions & 5 deletions examples/ticks_and_spines/spines.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,19 @@
ax1.set_title('bottom-left spines')

# Hide the right and top spines
ax1.spines['right'].set_visible(False)
ax1.spines['top'].set_visible(False)
ax1.spines.right.set_visible(False)
ax1.spines.top.set_visible(False)
# Only show ticks on the left and bottom spines
ax1.yaxis.set_ticks_position('left')
ax1.xaxis.set_ticks_position('bottom')

ax2.plot(x, y)

# Only draw spine between the y-ticks
ax2.spines['left'].set_bounds(-1, 1)
ax2.spines.left.set_bounds(-1, 1)
# Hide the right and top spines
ax2.spines['right'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax2.spines.right.set_visible(False)
ax2.spines.top.set_visible(False)
# Only show ticks on the left and bottom spines
ax2.yaxis.set_ticks_position('left')
ax2.xaxis.set_ticks_position('bottom')
Expand Down
6 changes: 3 additions & 3 deletions examples/ticks_and_spines/spines_bounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@
ax.set_yticks([-1, 0, 1])

# Only draw spine between the y-ticks
ax.spines['left'].set_bounds((-1, 1))
ax.spines.left.set_bounds((-1, 1))
# Hide the right and top spines
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines.right.set_visible(False)
ax.spines.top.set_visible(False)
# Only show ticks on the left and bottom spines
ax.yaxis.set_ticks_position('left')
ax.xaxis.set_ticks_position('bottom')
Expand Down
8 changes: 4 additions & 4 deletions examples/ticks_and_spines/spines_dropped.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
ax.set_title('dropped spines')

# Move left and bottom spines outward by 10 points
ax.spines['left'].set_position(('outward', 10))
ax.spines['bottom'].set_position(('outward', 10))
ax.spines.left.set_position(('outward', 10))
ax.spines.bottom.set_position(('outward', 10))
# Hide the right and top spines
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines.right.set_visible(False)
ax.spines.top.set_visible(False)
# Only show ticks on the left and bottom spines
ax.yaxis.set_ticks_position('left')
ax.xaxis.set_ticks_position('bottom')
Expand Down
6 changes: 3 additions & 3 deletions examples/ticks_and_spines/tick-formatters.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ def setup(ax, title):
"""Set up common parameters for the Axes in the example."""
# only show the bottom spine
ax.yaxis.set_major_locator(ticker.NullLocator())
ax.spines['right'].set_color('none')
ax.spines['left'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines.right.set_color('none')
ax.spines.left.set_color('none')
ax.spines.top.set_color('none')

# define tick positions
ax.xaxis.set_major_locator(ticker.MultipleLocator(1.00))
Expand Down
6 changes: 3 additions & 3 deletions examples/ticks_and_spines/tick-locators.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ def setup(ax, title):
"""Set up common parameters for the Axes in the example."""
# only show the bottom spine
ax.yaxis.set_major_locator(ticker.NullLocator())
ax.spines['right'].set_color('none')
ax.spines['left'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines.right.set_color('none')
ax.spines.left.set_color('none')
ax.spines.top.set_color('none')

ax.xaxis.set_ticks_position('bottom')
ax.tick_params(which='major', width=1.00, length=5)
Expand Down
8 changes: 4 additions & 4 deletions examples/userdemo/demo_gridspec06.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ def squiggle_xy(a, b, c, d):
# show only the outside spines
for ax in fig.get_axes():
ss = ax.get_subplotspec()
ax.spines['top'].set_visible(ss.is_first_row())
ax.spines['bottom'].set_visible(ss.is_last_row())
ax.spines['left'].set_visible(ss.is_first_col())
ax.spines['right'].set_visible(ss.is_last_col())
ax.spines.top.set_visible(ss.is_first_row())
ax.spines.bottom.set_visible(ss.is_last_row())
ax.spines.left.set_visible(ss.is_first_col())
ax.spines.right.set_visible(ss.is_last_col())

plt.show()
18 changes: 9 additions & 9 deletions lib/matplotlib/axes/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ def __init__(self, fig, rect,
# placeholder for any colorbars added that use this axes.
# (see colorbar.py):
self._colorbars = []
self.spines = self._gen_axes_spines()
self.spines = mspines.Spines.from_dict(self._gen_axes_spines())

# this call may differ for non-sep axes, e.g., polar
self._init_axis()
Expand Down Expand Up @@ -660,11 +660,11 @@ def get_window_extent(self, *args, **kwargs):
def _init_axis(self):
# This is moved out of __init__ because non-separable axes don't use it
self.xaxis = maxis.XAxis(self)
self.spines['bottom'].register_axis(self.xaxis)
self.spines['top'].register_axis(self.xaxis)
self.spines.bottom.register_axis(self.xaxis)
self.spines.top.register_axis(self.xaxis)
self.yaxis = maxis.YAxis(self)
self.spines['left'].register_axis(self.yaxis)
self.spines['right'].register_axis(self.yaxis)
self.spines.left.register_axis(self.yaxis)
self.spines.right.register_axis(self.yaxis)
self._update_transScale()

def set_figure(self, fig):
Expand Down Expand Up @@ -763,10 +763,10 @@ def get_xaxis_transform(self, which='grid'):
return self._xaxis_transform
elif which == 'tick1':
# for cartesian projection, this is bottom spine
return self.spines['bottom'].get_spine_transform()
return self.spines.bottom.get_spine_transform()
elif which == 'tick2':
# for cartesian projection, this is top spine
return self.spines['top'].get_spine_transform()
return self.spines.top.get_spine_transform()
else:
raise ValueError('unknown value for which')

Expand Down Expand Up @@ -839,10 +839,10 @@ def get_yaxis_transform(self, which='grid'):
return self._yaxis_transform
elif which == 'tick1':
# for cartesian projection, this is bottom spine
return self.spines['left'].get_spine_transform()
return self.spines.left.get_spine_transform()
elif which == 'tick2':
# for cartesian projection, this is top spine
return self.spines['right'].get_spine_transform()
return self.spines.right.get_spine_transform()
else:
raise ValueError('unknown value for which')

Expand Down
14 changes: 6 additions & 8 deletions lib/matplotlib/axes/_secondary_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,8 @@ def __init__(self, parent, orientation, location, functions, **kwargs):
otheraxis.set_major_locator(mticker.NullLocator())
otheraxis.set_ticks_position('none')

for st in self._otherstrings:
self.spines[st].set_visible(False)
for st in self._locstrings:
self.spines[st].set_visible(True)
self.spines[self._otherstrings].set_visible(False)
self.spines[self._locstrings].set_visible(True)

if self._pos < 0.5:
# flip the location strings...
Expand Down Expand Up @@ -259,13 +257,13 @@ def set_color(self, color):
"""
if self._orientation == 'x':
self.tick_params(axis='x', colors=color)
self.spines['bottom'].set_color(color)
self.spines['top'].set_color(color)
self.spines.bottom.set_color(color)
self.spines.top.set_color(color)
self.xaxis.label.set_color(color)
else:
self.tick_params(axis='y', colors=color)
self.spines['left'].set_color(color)
self.spines['right'].set_color(color)
self.spines.left.set_color(color)
self.spines.right.set_color(color)
self.yaxis.label.set_color(color)


Expand Down
Loading