Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Fix behaviour of Figure.clear() for SubplotParams #27183

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 43 commits into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
cf6032e
Fix behaviour of Figure.clear() for SubplotParams
eendebakpt Oct 24, 2023
68386fa
update credits
eendebakpt Oct 24, 2023
035a9c0
lint
eendebakpt Oct 24, 2023
c2c13ff
lint
eendebakpt Oct 24, 2023
247833c
lint
eendebakpt Oct 24, 2023
e2039f8
lint
eendebakpt Oct 24, 2023
1b76817
run boilerplate.py
eendebakpt Oct 25, 2023
51876fc
add tests
eendebakpt Oct 25, 2023
1470bf2
Update doc/users/next_whats_new/subplots_adjust.rst
eendebakpt Dec 6, 2023
199cc4a
update news entry
eendebakpt Dec 6, 2023
9772578
increase coverage
eendebakpt Dec 6, 2023
88eed8c
flake8
eendebakpt Jan 16, 2024
da31555
lint
eendebakpt Mar 19, 2024
12f26bd
Merge branch 'main' into clf_subplots_adjust
eendebakpt Jul 4, 2024
e39db47
lint
eendebakpt Jul 4, 2024
03ccff6
Merge branch 'main' into clf_subplots_adjust
eendebakpt Dec 6, 2024
0086dcf
Update lib/matplotlib/tests/test_figure.py
eendebakpt Dec 6, 2024
e9b5a61
Merge branch 'main' into clf_subplots_adjust
eendebakpt Jan 2, 2025
ded306c
Merge branch 'clf_subplots_adjust' of github.com:eendebakpt/matplotli…
eendebakpt Jan 2, 2025
5e40238
Merge branch 'main' into clf_subplots_adjust
eendebakpt Apr 14, 2025
e0b75ec
increase coverage
eendebakpt Apr 14, 2025
ddcc0b4
increase coverage
eendebakpt Apr 14, 2025
aa740f3
remove usage of rc_default
eendebakpt Apr 18, 2025
0766ec0
update whatsnew
eendebakpt Apr 18, 2025
50e9b46
whitespace
eendebakpt Apr 18, 2025
3690d94
whitespace
eendebakpt Apr 18, 2025
e119ab0
Apply suggestions from code review
eendebakpt Apr 21, 2025
275825f
review comments
eendebakpt Apr 21, 2025
b2cf506
Merge branch 'clf_subplots_adjust' of github.com:eendebakpt/matplotli…
eendebakpt Apr 21, 2025
7665053
fix merge conflicts
eendebakpt Apr 21, 2025
10d8216
remove duplicate test
eendebakpt Apr 21, 2025
d3f8db1
remove redundant test
eendebakpt Apr 21, 2025
6725328
ci
eendebakpt Apr 21, 2025
a91275e
ci
eendebakpt Apr 21, 2025
7d3e386
Update lib/matplotlib/tests/test_gridspec.py
eendebakpt Apr 22, 2025
9d772c4
Update lib/matplotlib/tests/test_gridspec.py
eendebakpt Apr 22, 2025
98df0da
Update doc/users/next_whats_new/subplots_adjust.rst
eendebakpt Apr 22, 2025
fac13d1
Update lib/matplotlib/gridspec.py
eendebakpt Apr 22, 2025
49d1eca
Update lib/matplotlib/gridspec.py
eendebakpt Apr 22, 2025
5c9674a
whitespace
eendebakpt Apr 22, 2025
78d699c
Merge branch 'main' into clf_subplots_adjust
eendebakpt Apr 22, 2025
5ad2d55
Update doc/users/next_whats_new/subplots_adjust.rst
timhoffm Apr 23, 2025
d5c9f7b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 23, 2025
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
10 changes: 10 additions & 0 deletions 10 doc/users/next_whats_new/subplots_adjust.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Resetting the subplot parameters for figure.clear()
---------------------------------------------------

When calling `.Figure.clear()` the settings for `.gridspec.SubplotParams` are restored to the default values.

The `.gridspec.SubplotParams` object has a new get method :meth:`~.SubplotParams.get_subplot_params` and a
method to reset the parameters to the defaults :meth:`~.SubplotParams.reset`


(contributed by @eendebakpt based on work by @fredrik-1)
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions 1 lib/matplotlib/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,7 @@ def clear(self, keep_observers=False):
self.texts = []
self.images = []
self.legends = []
self.subplotpars.reset()
if not keep_observers:
self._axobservers = cbook.CallbackRegistry()
self._suptitle = None
Expand Down
53 changes: 34 additions & 19 deletions 53 lib/matplotlib/gridspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
methods like `~.pyplot.subplots`, `~.pyplot.subplot_mosaic` and
`~.Figure.subfigures`. See the tutorial :ref:`arranging_axes` for a guide.
"""

from typing import Any
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved
import copy
import logging
from numbers import Integral
Expand Down Expand Up @@ -740,29 +740,36 @@ def __init__(self, left=None, bottom=None, right=None, top=None,

Parameters
----------
left : float
left : float, optional
The position of the left edge of the subplots,
as a fraction of the figure width.
right : float
right : float, optional
The position of the right edge of the subplots,
as a fraction of the figure width.
bottom : float
bottom : float, optional
The position of the bottom edge of the subplots,
as a fraction of the figure height.
top : float
top : float, optional
The position of the top edge of the subplots,
as a fraction of the figure height.
wspace : float
wspace : float, optional
The width of the padding between subplots,
as a fraction of the average Axes width.
hspace : float
hspace : float, optional
The height of the padding between subplots,
as a fraction of the average Axes height.
"""
for key in ["left", "bottom", "right", "top", "wspace", "hspace"]:
setattr(self, key, mpl.rcParams[f"figure.subplot.{key}"])
self.update(left, bottom, right, top, wspace, hspace)

def _repr_pretty_(self, p: Any, cycle: bool) -> None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply define __repr__?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__repr__ ends up at many places (logging, inside other repr of containers) and not everybody likes these kind of changes. The _repr_pretty_ is mainly used in interactive environments (spyder, jypyter noteobook, etc.) and visible to humans.

I do not think this change belongs in this PR though, so I removed it. Let me know if you want to to open a separate PR for this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's rare that we/users ever access this, so I don't really care. But I think if we do this, we can afford to do __repr__. We don't have precedence for _repr_pretty_ in the code base. Take or leave a separate PR.

del cycle
name = self.__class__.__name__
s = f"{name}(left={self.left}, bottom={self.bottom}, right={self.right}, "
s += f" top={self.top}, wspace={self.wspace}, hspace={self.hspace})"
p.text(s)

def update(self, left=None, bottom=None, right=None, top=None,
wspace=None, hspace=None):
"""
Expand All @@ -774,15 +781,23 @@ def update(self, left=None, bottom=None, right=None, top=None,
if ((bottom if bottom is not None else self.bottom)
>= (top if top is not None else self.top)):
raise ValueError('bottom cannot be >= top')
if left is not None:
self.left = left
if right is not None:
self.right = right
if bottom is not None:
self.bottom = bottom
if top is not None:
self.top = top
if wspace is not None:
self.wspace = wspace
if hspace is not None:
self.hspace = hspace

attributes = {'left': left, 'right': right, 'bottom': bottom, 'top': top,
'hspace': hspace, 'wspace': wspace}
for key, value in attributes.items():
if value is not None:
setattr(self, key, value)
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved

def reset(self):
"""Restore the positioning parameters to the default values"""
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved
for key in self.get_subplot_params().keys():
setattr(self, key, mpl.rcParams[f'figure.subplot.{key}'])

def get_subplot_params(self) -> dict[str, float]:
"""
Returns
-------
subplot_params : dictionary
A dictionary with the subplot parameters
"""
return self.__dict__.copy()
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 4 additions & 0 deletions 4 lib/matplotlib/gridspec.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,7 @@ class SubplotParams:
wspace: float | None = ...,
hspace: float | None = ...,
) -> None: ...
def get_subplot_params(
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved
self,
) -> dict[str, float]: ...
def reset(self) -> None: ...
38 changes: 38 additions & 0 deletions 38 lib/matplotlib/tests/test_figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -1770,6 +1770,44 @@ def test_warn_colorbar_mismatch():
subfig3_1.colorbar(im4_1)


def test_clf_subplotpars():
keys = ('left', 'right', 'bottom', 'top', 'wspace', 'hspace')
rc_params = {key: plt.rcParams['figure.subplot.'+key] for key in keys}

fig = plt.figure(1)
fig.subplots_adjust(left=0.1)
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved
fig.clf()
assert fig.subplotpars.get_subplot_params() == rc_params


def test_suplots_adjust_1():
fig = plt.figure(1)
wspace = 0
fig.subplots_adjust(wspace=wspace)
inDict = dict(left=0.1, right=0.7, bottom=0, top=0.9, hspace=0.05)
fig.subplots_adjust(**inDict)
inDict['wspace'] = wspace
assert fig.subplotpars.get_subplot_params() == inDict
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved


def test_suplots_adjust_2():
timhoffm marked this conversation as resolved.
Show resolved Hide resolved
fig = plt.figure(1)
fig.subplots_adjust(wspace=0)
inDict = dict(left=0.1, right=0.7, bottom=0, top=0.9, hspace=0.05)
fig.subplots_adjust(**inDict)
inDict['wspace'] = plt.rcParams['figure.subplot.wspace']
assert fig.subplotpars.get_subplot_params() == inDict


def test_suplots_adjust_plt():
plt.figure(1)
plt.subplots_adjust(wspace=0)
inDict = dict(left=0.1, right=0.7, bottom=0, top=0.9, hspace=0.05)
plt.subplots_adjust(**inDict)
inDict['wspace'] = plt.rcParams['figure.subplot.wspace']
assert plt.gcf().subplotpars.get_subplot_params() == inDict

eendebakpt marked this conversation as resolved.
Show resolved Hide resolved

def test_set_figure():
fig = plt.figure()
sfig1 = fig.subfigures()
Expand Down
33 changes: 33 additions & 0 deletions 33 lib/matplotlib/tests/test_gridspec.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import unittest
import matplotlib
import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
import pytest
Expand All @@ -9,6 +11,16 @@ def test_equal():
assert gs[:, 0] == gs[:, 0]


def test_update():
gs = gridspec.GridSpec(2, 1)

gs.update(left=.1)
assert gs.left == .1

with pytest.raises(AttributeError):
gs.update(lleft=.1)
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved


def test_width_ratios():
"""
Addresses issue #5835.
Expand All @@ -27,6 +39,22 @@ def test_height_ratios():
gridspec.GridSpec(1, 1, height_ratios=[2, 1, 3])


def test_SubplotParams():
s = gridspec.SubplotParams(.1, .1, .9, .9)
assert s.left == 0.1

with pytest.raises(ValueError):
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved
s.update(left=s.right + .01)

with pytest.raises(ValueError):
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved
s.update(bottom=s.top + .01)

with pytest.raises(ValueError):
s = gridspec.SubplotParams(.1, .1, .09, .9)
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved

s.reset()
assert s.left == matplotlib.rcParams['figure.subplot.left']
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved

def test_repr():
ss = gridspec.GridSpec(3, 3)[2, 1:3]
assert repr(ss) == "GridSpec(3, 3)[2:3, 1:3]"
Expand All @@ -48,3 +76,8 @@ def test_subplotspec_args():
gs = gridspec.GridSpecFromSubplotSpec(2, 1, subplot_spec=axs[0])
with pytest.raises(TypeError, match="subplot_spec must be type SubplotSpec"):
gs = gridspec.GridSpecFromSubplotSpec(2, 1, subplot_spec=axs)

s = gridspec.SubplotParams(.1, .1, .9, .9)
p = unittest.mock.MagicMock()
s._repr_pretty_(p, False)
assert 'SubplotParams' in p.method_calls[0].args[0]
eendebakpt marked this conversation as resolved.
Show resolved Hide resolved
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.