From 5918332ec9f79bd3dcb4dcc138cb84ef6856889b Mon Sep 17 00:00:00 2001 From: Garvey Zhou Date: Sun, 11 Dec 2022 17:40:16 -0500 Subject: [PATCH 1/6] added getters and setters subplotparams for figure --- lib/matplotlib/figure.py | 59 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 39517e14d0e3..886720145646 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1201,6 +1201,61 @@ def text(self, x, y, s, fontdict=None, **kwargs): self.stale = True return text + def set_subplotparams(self, subplotparams={}): + """ + Set the subplot layout parameters. + Accepts either a `.SubplotParams` object, from which the relevant + parameters are copied, or a dictionary of subplot layout parameters. + If a dictionary is provided, this function is a convenience wrapper for + `matplotlib.figure.Figure.subplots_adjust` + Parameters + ---------- + subplotparams : `~matplotlib.figure.SubplotParams` or dict with keys \ + "left", "bottom", "right", 'top", "wspace", "hspace"] , optional + SubplotParams object to copy new subplot parameters from, or a dict + of SubplotParams constructor arguments. + By default, an empty dictionary is passed, which maintains the + current state of the figure's `.SubplotParams` + See Also + -------- + matplotlib.figure.Figure.subplots_adjust + matplotlib.figure.Figure.get_subplotparams + """ + subplotparams_args = ["left", "bottom", "right", + "top", "wspace", "hspace"] + kwargs = {} + if isinstance(subplotparams, SubplotParams): + for key in subplotparams_args: + kwargs[key] = getattr(subplotparams, key) + elif isinstance(subplotparams, dict): + for key in subplotparams.keys(): + if key in subplotparams_args: + kwargs[key] = subplotparams[key] + else: + _api.warn_external( + f"'{key}' is not a valid key for set_subplotparams;" + " this key was ignored.") + else: + raise TypeError( + "subplotparams must be a dictionary of keyword-argument pairs or" + " an instance of SubplotParams()") + if kwargs == {}: + self.set_subplotparams(self.get_subplotparams()) + self.subplots_adjust(**kwargs) + + def get_subplotparams(self): + """ + Return the `.SubplotParams` object associated with the Figure. + Returns + ------- + `.SubplotParams` + See Also + -------- + matplotlib.figure.Figure.subplots_adjust + matplotlib.figure.Figure.get_subplotparams + """ + return self.subplotpars + @_docstring.dedent_interpd def colorbar( self, mappable, cax=None, ax=None, use_gridspec=True, **kwargs): @@ -2346,6 +2401,10 @@ def draw(self, renderer): @_docstring.interpd +@_api.define_aliases({ + "size_inches": ["figsize"], + "layout_engine": ["layout"] +}) class Figure(FigureBase): """ The top level container for all the plot elements. From 6b995ea938528034f2b3b41a10003290d10cb936 Mon Sep 17 00:00:00 2001 From: dutta712 Date: Wed, 17 May 2023 13:45:06 +0530 Subject: [PATCH 2/6] Added setter/getters for Figure for issue #24617 --- lib/matplotlib/figure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 886720145646..43a701e94b8d 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -2403,7 +2403,7 @@ def draw(self, renderer): @_docstring.interpd @_api.define_aliases({ "size_inches": ["figsize"], - "layout_engine": ["layout"] + "layout_engine": ["layout"], }) class Figure(FigureBase): """ From 965305b601405995cd9c43644921083fe5f5b9e7 Mon Sep 17 00:00:00 2001 From: dutta712 Date: Fri, 26 May 2023 18:37:03 +0530 Subject: [PATCH 3/6] initial fixes --- lib/matplotlib/figure.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 43a701e94b8d..ae61625d7357 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1204,23 +1204,27 @@ def text(self, x, y, s, fontdict=None, **kwargs): def set_subplotparams(self, subplotparams={}): """ Set the subplot layout parameters. + Accepts either a `.SubplotParams` object, from which the relevant parameters are copied, or a dictionary of subplot layout parameters. If a dictionary is provided, this function is a convenience wrapper for `matplotlib.figure.Figure.subplots_adjust` + Parameters ---------- - subplotparams : `~matplotlib.figure.SubplotParams` or dict with keys \ + subplotparams : `~matplotlib.figure.SubplotParams` or dict with keys "left", "bottom", "right", 'top", "wspace", "hspace"] , optional - SubplotParams object to copy new subplot parameters from, or a dict - of SubplotParams constructor arguments. - By default, an empty dictionary is passed, which maintains the - current state of the figure's `.SubplotParams` + SubplotParams object to copy new subplot parameters from, or a dict + of SubplotParams constructor arguments. + By default, an empty dictionary is passed, which maintains the + current state of the figure's `.SubplotParams` + See Also -------- matplotlib.figure.Figure.subplots_adjust matplotlib.figure.Figure.get_subplotparams """ + subplotparams_args = ["left", "bottom", "right", "top", "wspace", "hspace"] kwargs = {} @@ -1246,9 +1250,11 @@ def set_subplotparams(self, subplotparams={}): def get_subplotparams(self): """ Return the `.SubplotParams` object associated with the Figure. + Returns ------- `.SubplotParams` + See Also -------- matplotlib.figure.Figure.subplots_adjust @@ -2765,7 +2771,7 @@ def show(self, warn=True): self.canvas.manager.show() except NonGuiException as exc: if warn: - _api.warn_external(str(exc)) + api.warn_external(str(exc)) @property def axes(self): From 67f3846b2d986676dd61c004d6bb256960e60436 Mon Sep 17 00:00:00 2001 From: dutta712 Date: Fri, 26 May 2023 21:17:17 +0530 Subject: [PATCH 4/6] Fixed typo and removed whitespaces from blank lines --- lib/matplotlib/figure.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 925fb5504ebb..da2a50ffa2c6 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1209,7 +1209,7 @@ def set_subplotparams(self, subplotparams={}): parameters are copied, or a dictionary of subplot layout parameters. If a dictionary is provided, this function is a convenience wrapper for `matplotlib.figure.Figure.subplots_adjust` - + Parameters ---------- subplotparams : `~matplotlib.figure.SubplotParams` or dict with keys @@ -1218,7 +1218,7 @@ def set_subplotparams(self, subplotparams={}): of SubplotParams constructor arguments. By default, an empty dictionary is passed, which maintains the current state of the figure's `.SubplotParams` - + See Also -------- matplotlib.figure.Figure.subplots_adjust @@ -1250,11 +1250,11 @@ def set_subplotparams(self, subplotparams={}): def get_subplotparams(self): """ Return the `.SubplotParams` object associated with the Figure. - + Returns ------- `.SubplotParams` - + See Also -------- matplotlib.figure.Figure.subplots_adjust @@ -2771,7 +2771,7 @@ def show(self, warn=True): self.canvas.manager.show() except NonGuiException as exc: if warn: - api.warn_external(str(exc)) + _api.warn_external(str(exc)) @property def axes(self): From 49e2013c4a7c493aa7729ca811dc583f94d111f7 Mon Sep 17 00:00:00 2001 From: dutta712 Date: Sat, 27 May 2023 22:31:21 +0530 Subject: [PATCH 5/6] Added tests --- lib/matplotlib/tests/test_figure.py | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index 474331bf9149..8effd129a050 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -1611,3 +1611,42 @@ def test_get_constrained_layout_pads(): fig = plt.figure(layout=mpl.layout_engine.ConstrainedLayoutEngine(**params)) with pytest.warns(PendingDeprecationWarning, match="will be deprecated"): assert fig.get_constrained_layout_pads() == expected + + +def test_get_subplot_params(): + fig = plt.figure() + subplotparams_keys = ["left", "bottom", "right", "top", "wspace", "hspace"] + subplotparams = fig.get_subplotparams() + test_dict = {} + for key in subplotparams_keys: + attr = getattr(subplotparams, key) + assert attr == mpl.rcParams[f"figure.subplot.{key}"] + test_dict[key] = attr * 2 + + fig.set_subplotparams(test_dict) + for key, value in test_dict.items(): + assert getattr(fig.get_subplotparams(), key) == value + + test_dict['foo'] = 'bar' + with pytest.warns(UserWarning, + match="'foo' is not a valid key for set_subplotparams;" + " this key was ignored"): + fig.set_subplotparams(test_dict) + + with pytest.raises(TypeError, + match="subplotparams must be a dictionary of " + "keyword-argument pairs or " + "an instance of SubplotParams()"): + fig.set_subplotparams(['foo']) + + assert fig.subplotpars == fig.get_subplotparams() + + +def test_fig_get_set(): + varnames = filter(lambda var: var not in ['self', 'kwargs', 'args'], + Figure.__init__.__code__.co_varnames) + fig = plt.figure() + for var in varnames: + # if getattr fails then the getter and setter does not exist + getfunc = getattr(fig, f"get_{var}") + setfunc = getattr(fig, f"set_{var}") From 4e43c51ecaf4de9ae83aa3ef2c2325d8ea134ac4 Mon Sep 17 00:00:00 2001 From: dutta712 Date: Fri, 2 Jun 2023 10:28:56 +0530 Subject: [PATCH 6/6] added stubs for getters/setters subplotparams --- lib/matplotlib/figure.pyi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/matplotlib/figure.pyi b/lib/matplotlib/figure.pyi index 2b2bd9a49326..f1d294dbf115 100644 --- a/lib/matplotlib/figure.pyi +++ b/lib/matplotlib/figure.pyi @@ -241,6 +241,13 @@ class FigureBase(Artist): gridspec_kw: dict[str, Any] | None = ... ) -> dict[Any, Axes]: ... + def set_subplotparams( + self, + subplotparams: SubplotParams | dict[str, Any] = ..., + ) -> None: ... + + def get_subplotparams(self) -> SubplotParams: ... + class SubFigure(FigureBase): figure: Figure subplotpars: SubplotParams