From 6b63303c583fa3ca70e6ba2c965569b4c22bfe76 Mon Sep 17 00:00:00 2001 From: EthanAGit <149007871+EthanAGit@users.noreply.github.com> Date: Thu, 3 Oct 2024 07:07:46 -0400 Subject: [PATCH 1/3] issue #24617 fixed getter from #2509 This is my first open source contribution. I don't know how the setter works as I used someone else's working one, but I did get the getter to pass it's test. Added a figsize alias as well. --- lib/matplotlib/figure.py | 79 +++++++++++++++++++++++++++++ lib/matplotlib/figure.pyi | 2 + lib/matplotlib/tests/test_figure.py | 26 ++++++++++ 3 files changed, 107 insertions(+) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 73f1629180aa..e151ea7fb519 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -287,7 +287,64 @@ def set_figure(self, fig): figure = property(functools.partial(get_figure, root=True), set_figure, doc=("The root `Figure`. To get the parent of a `SubFigure`, " "use the `get_figure` method.")) + 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 + """ + subplotparms = [] + for subfig in self.subfigs: + subplotparms.append(subfig.get_subplotparams()) + return subplotparms def contains(self, mouseevent): """ Test whether the mouse event occurred on the figure. @@ -2865,6 +2922,28 @@ def set_tight_layout(self, tight): _tight_parameters = tight if isinstance(tight, dict) else {} self.set_layout_engine(_tight, **_tight_parameters) self.stale = True + 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 + + @property + def get_figsize(self): + return self.get_size_inches() + @property + def set_figsize(self, w, h=None, forward=True): + self.set_size_inches(self, w, h=None, forward=True) + def get_constrained_layout(self): """ diff --git a/lib/matplotlib/figure.pyi b/lib/matplotlib/figure.pyi index ade4cfd6f16d..b37c464689ee 100644 --- a/lib/matplotlib/figure.pyi +++ b/lib/matplotlib/figure.pyi @@ -67,6 +67,8 @@ class FigureBase(Artist): def get_figure(self, root: Literal[False]) -> Figure | SubFigure: ... @overload def get_figure(self, root: bool = ...) -> Figure | SubFigure: ... + + def get_subplotparams(self) -> SubplotParams: ... def set_frameon(self, b: bool) -> None: ... @property def frameon(self) -> bool: ... diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index 99045e773d02..9abfd5b17318 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -241,7 +241,33 @@ def test_gca(): assert fig.axes == [ax0, ax1] assert fig.gca() is ax1 +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_add_subplot_subclass(): fig = plt.figure() fig.add_subplot(axes_class=Axes) From 3ebf2911385c4d3f7f24d794a29bb30bcef8527c Mon Sep 17 00:00:00 2001 From: EthanAGit <149007871+EthanAGit@users.noreply.github.com> Date: Thu, 3 Oct 2024 07:37:49 -0400 Subject: [PATCH 2/3] Update figure.py --- lib/matplotlib/figure.py | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index e151ea7fb519..5c8f0ed2b3c0 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -2937,6 +2937,49 @@ def get_subplotparams(self): return self.subplotpars + 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) + @property def get_figsize(self): return self.get_size_inches() From f79e9c5c69a3b4ddfea9b8fe161c45e941db300e Mon Sep 17 00:00:00 2001 From: EthanAGit <149007871+EthanAGit@users.noreply.github.com> Date: Thu, 3 Oct 2024 18:55:55 -0400 Subject: [PATCH 3/3] update --- lib/matplotlib/figure.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 5c8f0ed2b3c0..60e9a40252bf 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -287,16 +287,17 @@ def set_figure(self, fig): figure = property(functools.partial(get_figure, root=True), set_figure, doc=("The root `Figure`. To get the parent of a `SubFigure`, " "use the `get_figure` method.")) + 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` + .. 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. @@ -304,7 +305,7 @@ def set_subplotparams(self, subplotparams={}): current state of the figure's `.SubplotParams` See Also -------- -matplotlib.figure.Figure.subplots_adjust + matplotlib.figure.Figure.subplots_adjust matplotlib.figure.Figure.get_subplotparams """ @@ -2922,6 +2923,7 @@ def set_tight_layout(self, tight): _tight_parameters = tight if isinstance(tight, dict) else {} self.set_layout_engine(_tight, **_tight_parameters) self.stale = True + def get_subplotparams(self): """ Return the `.SubplotParams` object associated with the Figure. @@ -2933,20 +2935,18 @@ def get_subplotparams(self): matplotlib.figure.Figure.subplots_adjust matplotlib.figure.Figure.get_subplotparams """ - - return self.subplotpars 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 + .. 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. @@ -2954,10 +2954,9 @@ def set_subplotparams(self, subplotparams={}): current state of the figure's `.SubplotParams` See Also -------- - matplotlib.figure.Figure.subplots_adjust + matplotlib.figure.Figure.subplots_adjust matplotlib.figure.Figure.get_subplotparams """ - subplotparams_args = ["left", "bottom", "right", "top", "wspace", "hspace"] kwargs = {} @@ -2983,6 +2982,7 @@ def set_subplotparams(self, subplotparams={}): @property def get_figsize(self): return self.get_size_inches() + @property def set_figsize(self, w, h=None, forward=True): self.set_size_inches(self, w, h=None, forward=True)