A couple years later, the issue quoted by Gabriel has been updated with the following and closed as of April 2019.
This would have to be part of a major overhaul of the tick and gridline system, which I suspect might have to be just one component of an even more major refactoring, so I think the solution for the foreseeable future is the documentation tweak in #13995.
One workaround for cases where you need a grid with arbitrary zorder values is to emulate grid()
using plot()
. I wrote the function to replicate the standard grid() behavior as closely as possible (using the rcParam values by default).
import matplotlib.pyplot as plt
from matplotlib import rcParams
import numpy as np
# emulate grid using Axes.plot()
def zorder_grid(ax=None, zorder=1.5, which=None, axis=None, alpha=None,
color=None, linestyle=None, linewidth=None, **kwargs):
# Honor rcParams values if keywords not specified
if ax is None:
ax = plt.gca()
if which is None:
which = rcParams['axes.grid.which']
if axis is None:
axis = rcParams['axes.grid.axis']
if alpha is None:
alpha = rcParams['grid.alpha']
if color is None:
color = rcParams['grid.color']
if linestyle is None:
linestyle = rcParams['grid.linestyle']
if linewidth is None:
linewidth = rcParams['grid.linewidth']
# get coordinates for grid lines
xlim = ax.get_xlim()
ylim = ax.get_ylim()
xticks = []
yticks = []
if which in ['major', 'both']:
xticks = np.concatenate((xticks, ax.get_xticks()))
yticks = np.concatenate((yticks, ax.get_yticks()))
if which in ['minor', 'both']:
xticks = np.concatenate((xticks, ax.get_xticks(minor=True)))
yticks = np.concatenate((yticks, ax.get_yticks(minor=True)))
# plot grid using Axes.plot()
if axis in ['x', 'both']:
for tick in xticks:
ax.plot([tick, tick], ylim, linestyle=linestyle, color=color,
linewidth=linewidth, alpha=alpha, zorder=zorder, **kwargs)
if axis in ['y', 'both']:
for tick in yticks:
ax.plot(xlim, [tick, tick], linestyle=linestyle, color=color,
linewidth=linewidth, alpha=alpha, zorder=zorder, **kwargs)
Caveats:
- The x and y limits must be manually set before calling
zorder_grid()
. If specifying the ticks manually, that would also need to be done prior to plotting grid lines.
- This will have issues if the axis limits and/or ticks change dynamically (e.g. animations). Possible solutions might be clearing the axis between frames or returning a Line2D list and toggling visibility.
The function can be called as follows to produce the desired output in the MWE (any zorder < 1 would work).
pnts = np.array([[1., 1.], [1., 1.2]])
plt.scatter(pnts[:,0], pnts[:,1])
plt.ylim([0, 2])
plt.xlim([0, 2])
zorder_grid(zorder=0.99, linestyle='-', color='r')
plt.savefig('testfig.png', dpi=350)
Figure generated by the above code.
