Skip to content
Open
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
25 changes: 25 additions & 0 deletions doc/release/next_whats_new/get_gridlines_which.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
``Axis.get_gridlines`` can return minor gridlines
-------------------------------------------------
`~matplotlib.axis.Axis.get_gridlines` now accepts a *which* keyword argument
to select major, minor, or both groups of gridlines. The default value
``'major'`` preserves the previous behavior.

.. plot::
:include-source: true
:alt: Highlight every minor gridline of the x-axis in red.

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot(range(10))
ax.minorticks_on()
ax.grid(which='both')

for line in ax.xaxis.get_gridlines(which='minor'):
line.set_color('red')

plt.show()

Previously there was no public API to access minor gridlines, so downstream
libraries reached into the private ``Axis._minor_tick_kw`` mapping to detect
their state.
8 changes: 6 additions & 2 deletions lib/matplotlib/axes/_base.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -403,9 +403,13 @@ class _AxesBase(martist.Artist):
# itself with a method modified from the Axis methods for the x or y Axis.
# As such, they are typed according to the resultant method rather than as that object.

def get_xgridlines(self) -> list[Line2D]: ...
def get_xgridlines(
self, which: Literal["major", "minor", "both"] = ...
) -> list[Line2D]: ...
def get_xticklines(self, minor: bool = ...) -> list[Line2D]: ...
def get_ygridlines(self) -> list[Line2D]: ...
def get_ygridlines(
self, which: Literal["major", "minor", "both"] = ...
) -> list[Line2D]: ...
def get_yticklines(self, minor: bool = ...) -> list[Line2D]: ...
def _sci(self, im: ColorizingArtist) -> None: ...
def get_autoscalex_on(self) -> bool: ...
Expand Down
38 changes: 33 additions & 5 deletions lib/matplotlib/axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -1470,11 +1470,39 @@ def draw(self, renderer):
renderer.close_group(__name__)
self.stale = False

def get_gridlines(self):
r"""Return this Axis' grid lines as a list of `.Line2D`\s."""
ticks = self.get_major_ticks()
return cbook.silent_list('Line2D gridline',
[tick.gridline for tick in ticks])
def get_gridlines(self, which='major'):
r"""
Return this Axis' grid lines as a list of `.Line2D`\s.

Parameters
----------
which : {'major', 'minor', 'both'}, default: 'major'
Which set of gridlines to return.

.. versionchanged:: 3.11
Added the *which* parameter; previously only major gridlines
were returned.

Returns
-------
list of `.Line2D`
The gridline `.Line2D` objects. For ``which='both'``, major
gridlines come before minor gridlines.

Notes
-----
The returned list contains every gridline managed by this Axis
regardless of its visibility. Use ``Line2D.get_visible()`` on each
returned object to check whether a particular gridline is currently
drawn.
"""
_api.check_in_list(['major', 'minor', 'both'], which=which)
lines = []
if which in ('major', 'both'):
lines.extend(tick.gridline for tick in self.get_major_ticks())
if which in ('minor', 'both'):
lines.extend(tick.gridline for tick in self.get_minor_ticks())
return cbook.silent_list('Line2D gridline', lines)

def set_label(self, s):
"""Assigning legend labels is not supported. Raises RuntimeError."""
Expand Down
4 changes: 3 additions & 1 deletion lib/matplotlib/axis.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,9 @@ class Axis(martist.Artist):
self, renderer: RendererBase | None = ..., *, for_layout_only: bool = ...
) -> Bbox | None: ...
def get_tick_padding(self) -> float: ...
def get_gridlines(self) -> list[Line2D]: ...
def get_gridlines(
self, which: Literal["major", "minor", "both"] = ...
) -> list[Line2D]: ...
def get_label(self) -> Text: ...
def get_offset_text(self) -> Text: ...
def get_pickradius(self) -> float: ...
Expand Down
48 changes: 48 additions & 0 deletions lib/matplotlib/tests/test_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -6300,6 +6300,54 @@ def test_grid():
assert not ax.xaxis.majorTicks[0].gridline.get_visible()


def test_get_gridlines_which():
"""`Axis.get_gridlines` selects major, minor, or both via *which*."""
fig, ax = plt.subplots()
ax.minorticks_on()

n_major = len(ax.xaxis.get_major_ticks())
n_minor = len(ax.xaxis.get_minor_ticks())

major_lines = ax.xaxis.get_gridlines()
assert len(major_lines) == n_major
assert major_lines == ax.xaxis.get_gridlines(which='major')

minor_lines = ax.xaxis.get_gridlines(which='minor')
assert len(minor_lines) == n_minor
assert all(line not in major_lines for line in minor_lines)

both_lines = ax.xaxis.get_gridlines(which='both')
assert len(both_lines) == n_major + n_minor
assert both_lines[:n_major] == major_lines
assert both_lines[n_major:] == minor_lines

with pytest.raises(ValueError,
match="'invalid' is not a valid value for which"):
ax.xaxis.get_gridlines(which='invalid')


def test_get_gridlines_visibility_reflects_grid_state():
"""Visibility of returned gridlines tracks the active grid state."""
fig, ax = plt.subplots()
ax.minorticks_on()

ax.grid(visible=False, which='both')
fig.canvas.draw()
assert not any(line.get_visible()
for line in ax.xaxis.get_gridlines(which='both'))

ax.grid(visible=True, which='major')
fig.canvas.draw()
assert all(line.get_visible() for line in ax.xaxis.get_gridlines('major'))
assert not any(line.get_visible()
for line in ax.xaxis.get_gridlines('minor'))

ax.grid(visible=True, which='minor')
fig.canvas.draw()
assert all(line.get_visible()
for line in ax.xaxis.get_gridlines(which='both'))


def test_grid_color_with_alpha():
"""Test that grid(color=(..., alpha)) respects the alpha value."""
fig, ax = plt.subplots()
Expand Down
Loading