From fc18909dd0541a9555e1356e8f89361fe29cbdd3 Mon Sep 17 00:00:00 2001 From: Jay Stanley Date: Fri, 5 Nov 2021 15:48:11 -0500 Subject: [PATCH 1/7] Updated figure to have getters and setters for all constructor arguments. refactored layout setting. added ability to change subplotparams post hoc. added figsize getter/setter convenience function in order to match the constructor signature of figure. added tests. --- lib/matplotlib/figure.py | 197 ++++++++++++++++++++++++---- lib/matplotlib/tests/test_figure.py | 188 ++++++++++++++++++++++++-- 2 files changed, 349 insertions(+), 36 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 04f0e73d2671..ae364df47b2d 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1204,6 +1204,32 @@ def subplots_adjust(self, left=None, bottom=None, right=None, top=None, ax._set_position(ax.get_subplotspec().get_position(self)) self.stale = True + def set_subplotpars(self, 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_subplotpars;" + " this key was ignored.") + else: + raise TypeError( + "subplotpars must be a dictionary of keyword-argument pairs or " + "an instance of SubplotParams()") + if kwargs == {}: + self.set_subplotpars(self.get_subplotpars()) + self.subplots_adjust(**kwargs) + + def get_subplotpars(self): + return self.subplotpars + def align_xlabels(self, axs=None): """ Align the xlabels of subplots in the same subplot column if label @@ -2231,24 +2257,6 @@ def __init__(self, """ super().__init__(**kwargs) - if layout is not None: - if tight_layout is not None: - _api.warn_external( - "The Figure parameters 'layout' and 'tight_layout' " - "cannot be used together. Please use 'layout' only.") - if constrained_layout is not None: - _api.warn_external( - "The Figure parameters 'layout' and 'constrained_layout' " - "cannot be used together. Please use 'layout' only.") - if layout == 'constrained': - tight_layout = False - constrained_layout = True - elif layout == 'tight': - tight_layout = True - constrained_layout = False - else: - _api.check_in_list(['constrained', 'tight'], layout=layout) - self.callbacks = cbook.CallbackRegistry() # Callbacks traditionally associated with the canvas (and exposed with # a proxy property), but that actually need to be on the figure for @@ -2299,15 +2307,12 @@ def __init__(self, self.subplotpars = subplotpars # constrained_layout: - self._constrained = False - - self.set_tight_layout(tight_layout) + self._axstack = _AxesStack() # track all figure axes and current axes self.clf() self._cachedRenderer = None - - self.set_constrained_layout(constrained_layout) + self.set_layout(layout,tight_layout,constrained_layout) # list of child gridspecs for this figure self._gridspecs = [] @@ -2399,11 +2404,96 @@ def _set_dpi(self, dpi, forward=True): dpi = property(_get_dpi, _set_dpi, doc="The resolution in dots per inch.") + @property + def layout(self): + if hasattr(self,'_constrained'): + if self.get_constrained_layout(): + layout = 'constrained' + elif self.get_tight_layout(): + layout = 'tight' + else: + layout = None + else: + layout = None + return layout + + def get_layout(self): + return self.layout + + def set_layout(self,layout=None, tight_layout=None,constrained_layout=None): + if ( + layout is None and + tight_layout is None and + constrained_layout is None + ): + layout = self.get_layout() + + if layout is not None: + layout_clash = False + bool_conflict = False + type_conflict = False + + if layout == 'constrained': + layoutstr = 'constrained_layout' + falselayoutstr = 'tight_layout' + layout_clash = tight_layout not in [False,None] + tight_layout=False + bool_conflict = ( + isinstance(constrained_layout,bool) and + not constrained_layout + ) + type_conflict = not isinstance(constrained_layout, + (dict, bool, type(None))) + if bool_conflict or type_conflict or constrained_layout is None: + constrained_layout=True + + + elif layout == 'tight': + layoutstr = 'tight_layout' + falselayoutstr = 'constrained_layout' + layout_clash = constrained_layout not in [False,None] + constrained_layout = False + bool_conflict = ( + isinstance(tight_layout,bool) and + not tight_layout + ) + type_conflict = not isinstance(tight_layout, + (dict, bool, type(None))) + if bool_conflict or type_conflict or tight_layout is None: + tight_layout=True + else: + _api.check_in_list(['constrained', 'tight'], layout=layout) + + if layout_clash: + _api.warn_external(f"Figure parameters " + f"'layout'=='{layout}' and " + f"'{falselayoutstr}'==True cannot " + f"be used together. " + f"Please use 'layout' only.") + if bool_conflict: + _api.warn_external(f"Figure parameters " + f"'layout'=='{layout}' and " + f"'{layoutstr}'==False cannot be " + f"used together. " + f"Please use 'layout' only.") + if type_conflict: + _api.warn_external(f"Figure parameters " + f"'layout'=='{layout}' and " + f"'{layoutstr}' cannot be " + f"used together if '{layoutstr}' is " + f"not True or a dictionary of " + f"{layoutstr} arguments. " + f"Please use 'layout' only.") + + self._constrained = False + self.set_tight_layout(tight_layout) + self.set_constrained_layout(constrained_layout) + def get_tight_layout(self): """Return whether `.tight_layout` is called when drawing.""" return self._tight - def set_tight_layout(self, tight): + def set_tight_layout(self, tight = None): """ Set whether and how `.tight_layout` is called when drawing. @@ -2429,7 +2519,7 @@ def get_constrained_layout(self): """ return self._constrained - def set_constrained_layout(self, constrained): + def set_constrained_layout(self, constrained = None): """ Set whether ``constrained_layout`` is used upon drawing. If None, :rc:`figure.constrained_layout.use` value will be used. @@ -2684,6 +2774,63 @@ def get_size_inches(self): """ return np.array(self.bbox_inches.p1) + def set_figsize(self, w, h = None): + """ + Set the figure size in inches. + Convenience wrapper for matplotlib.figure.Figure.set_size_inches. + + Call signatures:: + + fig.set_figsize(w, h) # OR + fig.set_figsize((w, h)) + + Parameters + ---------- + w : (float, float) or float + Width and height in inches (if height not specified as a separate + argument) or width. + h : float + Height in inches. + forward : bool, default: True + If ``True``, the canvas size is automatically updated, e.g., + you can resize the figure window from the shell. + + See Also + -------- + matplotlib.figure.Figure.get_figsize + matplotlib.figure.Figure.set_size_inches + matplotlib.figure.Figure.set_figwidth + matplotlib.figure.Figure.set_figheight + + Notes + ----- + To transform from pixels to inches divide by `Figure.dpi`. + """ + self.set_size_inches(w,h) + + def get_figsize(self): + """ + Return the current size of the figure in inches. + Convenience wrapper for matplotlib.figure.Figure.get_size_inches. + + Returns + ------- + ndarray + The size (width, height) of the figure in inches. + + See Also + -------- + matplotlib.figure.Figure.set_figsize + matplotlib.figure.Figure.get_size_inches + matplotlib.figure.Figure.get_figwidth + matplotlib.figure.Figure.get_figheight + + Notes + ----- + The size in pixels can be obtained by multiplying with `Figure.dpi`. + """ + return self.get_size_inches() + def get_figwidth(self): """Return the figure width in inches.""" return self.bbox_inches.width diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index cb8f63893aea..ec728cb71e93 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -10,12 +10,13 @@ import pytest from PIL import Image + import matplotlib as mpl from matplotlib import cbook, rcParams from matplotlib._api.deprecation import MatplotlibDeprecationWarning from matplotlib.testing.decorators import image_comparison, check_figures_equal from matplotlib.axes import Axes -from matplotlib.figure import Figure +from matplotlib.figure import Figure, SubplotParams from matplotlib.ticker import AutoMinorLocator, FixedFormatter, ScalarFormatter import matplotlib.pyplot as plt import matplotlib.dates as mdates @@ -350,6 +351,10 @@ def test_set_fig_size(): assert fig.get_figwidth() == 1 assert fig.get_figheight() == 3 + fig.set_figsize(2,4) + assert fig.get_figsize()[0] == 2 + assert fig.get_figsize()[1] == 4 + def test_axes_remove(): fig, axs = plt.subplots(2, 2) @@ -541,29 +546,179 @@ def test_valid_layouts(): def test_invalid_layouts(): + + def assert_is_tight(fig): + assert fig.get_tight_layout() + assert not fig.get_constrained_layout() + assert fig.layout == 'tight' + def assert_is_constrained(fig): + assert not fig.get_tight_layout() + assert fig.get_constrained_layout() + assert fig.layout == 'constrained' + def assert_neither(fig): + assert not fig.get_tight_layout() + assert not fig.get_constrained_layout() + assert fig.layout is None fig, ax = plt.subplots(constrained_layout=True) with pytest.warns(UserWarning): # this should warn, fig.subplots_adjust(top=0.8) - assert not(fig.get_constrained_layout()) - + assert_neither(fig) # Using layout + (tight|constrained)_layout warns, but the former takes # precedence. - with pytest.warns(UserWarning, match="Figure parameters 'layout' and " - "'tight_layout' cannot"): + + # check the set_layout function on figure construction: + with pytest.warns(UserWarning, match="Figure parameters 'layout'=='tight' " + "and 'tight_layout'==False cannot"): fig = Figure(layout='tight', tight_layout=False) - assert fig.get_tight_layout() - assert not fig.get_constrained_layout() - with pytest.warns(UserWarning, match="Figure parameters 'layout' and " - "'constrained_layout' cannot"): + assert_is_tight(fig) + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='constrained' and 'constrained_layout'==False cannot"): fig = Figure(layout='constrained', constrained_layout=False) - assert not fig.get_tight_layout() - assert fig.get_constrained_layout() + assert_is_constrained(fig) + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='tight' and 'constrained_layout'==True cannot"): + fig = Figure(layout='tight', constrained_layout=True) + assert_is_tight(fig) + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='constrained' and 'tight_layout'==True cannot"): + fig = Figure(layout='constrained', tight_layout=True) + assert_is_constrained(fig) + + with pytest.warns(Warning) as warninfo: + fig = Figure(layout='tight', + tight_layout=False, + constrained_layout=True) + warns = {(warn.category, warn.message.args[0]) for warn in warninfo} + expected = { + (UserWarning, "Figure parameters 'layout'=='tight' " + "and 'tight_layout'==False cannot be used together. " + "Please use 'layout' only."), + (UserWarning,"Figure parameters 'layout'=='tight' " + "and 'constrained_layout'==True cannot be used together. " + "Please use 'layout' only.")} + assert_is_tight(fig) + assert warns==expected + with pytest.warns(Warning) as warninfo: + fig = Figure(layout='constrained', + tight_layout=True, + constrained_layout=False) + warns = {(warn.category, warn.message.args[0]) for warn in warninfo} + expected = { + (UserWarning, "Figure parameters 'layout'=='constrained' " + "and 'tight_layout'==True cannot be used together. " + "Please use 'layout' only."), + (UserWarning,"Figure parameters 'layout'=='constrained' " + "and 'constrained_layout'==False cannot be used together. " + "Please use 'layout' only.")} + assert_is_constrained(fig) + assert warns==expected + with pytest.raises(ValueError, match="'foobar' is not a valid value for layout"): Figure(layout='foobar') + # now check the set_layout function after figure_construction + fig = Figure(layout='tight') + with pytest.warns(UserWarning, match="Figure parameters 'layout'=='tight' " + "and 'tight_layout'==False cannot"): + fig.set_layout(layout='tight', tight_layout=False) + assert_is_tight(fig) + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='constrained' and 'constrained_layout'==False cannot"): + fig.set_layout(layout='constrained', constrained_layout=False) + assert_is_constrained(fig) + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='tight' and 'constrained_layout'==True cannot"): + fig.set_layout(layout='tight', constrained_layout=True) + assert_is_tight(fig) + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='constrained' and 'tight_layout'==True cannot"): + fig.set_layout(layout='constrained', tight_layout=True) + assert_is_constrained(fig) + + with pytest.warns(Warning) as warninfo: + fig.set_layout(layout='tight', + tight_layout=False, + constrained_layout=True) + warns = {(warn.category, warn.message.args[0]) for warn in warninfo} + expected = { + (UserWarning, "Figure parameters 'layout'=='tight' " + "and 'tight_layout'==False cannot be used together. " + "Please use 'layout' only."), + (UserWarning,"Figure parameters 'layout'=='tight' " + "and 'constrained_layout'==True cannot be used together. " + "Please use 'layout' only.")} + assert_is_tight(fig) + assert warns==expected + with pytest.warns(Warning) as warninfo: + fig.set_layout(layout='constrained', + tight_layout=True, + constrained_layout=False) + warns = {(warn.category, warn.message.args[0]) for warn in warninfo} + expected = { + (UserWarning, "Figure parameters 'layout'=='constrained' " + "and 'tight_layout'==True cannot be used together. " + "Please use 'layout' only."), + (UserWarning,"Figure parameters 'layout'=='constrained' " + "and 'constrained_layout'==False cannot be used together. " + "Please use 'layout' only.")} + assert_is_constrained(fig) + assert warns==expected +def test_set_subplotpars(): + subplotparams_keys = ["left", "bottom", "right", "top", "wspace", "hspace"] + fig = plt.figure() + subplotparams = fig.get_subplotpars() + test_dict = {} + default_dict = {} + for key in subplotparams_keys: + attr = getattr(subplotparams,key) + assert attr == mpl.rcParams[f"figure.subplot.{key}"] + default_dict[key] = attr + test_dict[key] = attr * 2 + + subplotparams.update(left=test_dict['left']) + assert fig.get_subplotpars().left == test_dict['left'] + + fig.subplots_adjust(**default_dict) + assert fig.get_subplotpars().left == default_dict['left'] + + fig.set_subplotpars(test_dict) + for key, value in test_dict.items(): + assert getattr(fig.get_subplotpars(),key) == value + + test_subplotparams = SubplotParams() + fig.set_subplotpars(test_subplotparams) + for key,value in default_dict.items(): + assert getattr(fig.get_subplotpars(),key) == value + + fig.set_subplotpars(test_dict) + for key,value in test_dict.items(): + assert getattr(fig.get_subplotpars(),key) == value + + test_dict['foo'] = 'bar' + with pytest.warns(UserWarning, + match ="'foo' is not a valid key for set_subplotpars;" + " this key was ignored"): + fig.set_subplotpars(test_dict) + + with pytest.raises(TypeError, + match="subplotpars must be a dictionary of keyword-argument pairs or " + "an instance of SubplotParams()"): + fig.set_subplotpars(['foo']) + + fig.set_subplotpars({}) + with pytest.raises(AttributeError): # test_dict['foo'] = 'bar' + # but fig.get_subplotpars().foo should be invalid + for key,value in test_dict.items(): + assert getattr(fig.get_subplotpars(),key) == value @check_figures_equal(extensions=["png", "pdf"]) def test_add_artist(fig_test, fig_ref): @@ -1226,3 +1381,14 @@ def test_kwargs_pass(): assert fig.get_label() == 'whole Figure' assert sub_fig.get_label() == 'sub figure' + +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 2775180af8c2aa9125253c8c5b9e1ef1a623d6ae Mon Sep 17 00:00:00 2001 From: Jay Stanley Date: Fri, 5 Nov 2021 16:03:29 -0500 Subject: [PATCH 2/7] docs --- lib/matplotlib/figure.py | 48 ++++++++++++++++++++++++++++- lib/matplotlib/tests/test_figure.py | 5 ++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index ae364df47b2d..75c87b1ef09a 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1191,6 +1191,11 @@ def subplots_adjust(self, left=None, bottom=None, right=None, top=None, hspace : float, optional The height of the padding between subplots, as a fraction of the average Axes height. + + See Also + -------- + matplotlib.figure.Figure.set_subplotpars + matplotlib.figure.Figure.get_subplotpars """ if self.get_constrained_layout(): self.set_constrained_layout(False) @@ -1205,6 +1210,29 @@ def subplots_adjust(self, left=None, bottom=None, right=None, top=None, self.stale = True def set_subplotpars(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, optional + SubplotParams object to copy new subplot parameters from, or a dict + of SubplotParams constructor arguments, i.e., a dictionary with + any of ["left", "bottom", "right", 'top", "wspace", "hspace"] as its + keys. + 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_subplotpars + """ + subplotparams_args = ["left", "bottom", "right", "top", "wspace", "hspace"] kwargs = {} @@ -1228,6 +1256,18 @@ def set_subplotpars(self, subplotparams = {}): self.subplots_adjust(**kwargs) def get_subplotpars(self): + """ + Return the SubplotParams object associated with the Figure. + + Returns + ------- + `.SubplotParams` + + See Also + -------- + matplotlib.figure.Figure.subplots_adjust + matplotlib.figure.Figure.get_subplotpars + """ return self.subplotpars def align_xlabels(self, axs=None): @@ -2420,7 +2460,13 @@ def layout(self): def get_layout(self): return self.layout - def set_layout(self,layout=None, tight_layout=None,constrained_layout=None): + def set_layout(self,layout=None, tight_layout=None, + constrained_layout=None): + """ + Set the figure layout specification, optionally setting how the layout + is called. + When providing a dict to tight_layout + """ if ( layout is None and tight_layout is None and diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index ec728cb71e93..f23bbf77b8fe 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -544,6 +544,10 @@ def test_valid_layouts(): assert not fig.get_tight_layout() assert fig.get_constrained_layout() + fig = Figure(constrained_layout = {'pad':1}) + assert not fig.get_tight_layout() + assert fig.get_constrained_layout() + def test_invalid_layouts(): @@ -1391,4 +1395,3 @@ def test_fig_get_set(): getfunc = getattr(fig,f"get_{var}") setfunc = getattr(fig,f"set_{var}") - From cc4f860251f710c7ba6e1051c6063a55246b0df6 Mon Sep 17 00:00:00 2001 From: Jay Stanley Date: Fri, 5 Nov 2021 16:35:42 -0500 Subject: [PATCH 3/7] added more test conditions for layout function --- lib/matplotlib/figure.py | 68 ++++++++++++++++-- lib/matplotlib/tests/test_figure.py | 106 +++++++++++++++++++++++++--- 2 files changed, 160 insertions(+), 14 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 75c87b1ef09a..f6a44b37b0d8 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -2446,6 +2446,9 @@ def _set_dpi(self, dpi, forward=True): @property def layout(self): + """ + Return the current figure layout solver. + """ if hasattr(self,'_constrained'): if self.get_constrained_layout(): layout = 'constrained' @@ -2458,14 +2461,64 @@ def layout(self): return layout def get_layout(self): + """ + Return the current figure layout solver. + """ return self.layout def set_layout(self,layout=None, tight_layout=None, constrained_layout=None): """ - Set the figure layout specification, optionally setting how the layout - is called. - When providing a dict to tight_layout + Set the figure layout specification. (Optionally) sets how + `.tight_layout` or `.constrained_layout` is called when a dict is + provided to tight_layout or constrained_layout. + + + If `layout` is not None, the layout solver is determined exclusively by + `layout`, regardless of `tight_layout` or `constrained_layout`, + but optional padding parameters stored in `tight_layout` or + `constrained_layout` are used with the respective layout. For instance, + if `layout`=='tight', 'tight_layout==False', and `constrained_layout`== + True, `tight_layout` with default paddings is used to format the figure. + If `layout`=='constrained', `tight_layout`=={'pad':1}, and + `constrained_layout`=={'w_pad':1}, then + `.constrained_layout` is called with padding parameters {'w_pad':1}. + If `layout` is None, `tight_layout` and `constrained_layout` are + mutually exclusive. That is, only one can be True or a dict. + + Parameters + ---------- + layout : {'constrained', 'tight', None}, optional + The layout mechanism for positioning of plot elements. + Supported values: + + - 'constrained': The constrained layout solver usually gives the + best layout results and is thus recommended. However, it is + computationally expensive and can be slow for complex figures + with many elements. + + See :doc:`/tutorials/intermediate/constrainedlayout_guide` + for examples. + + - 'tight': Use the tight layout mechanism. This is a relatively + simple algorithm, that adjusts the subplot parameters so that + decorations like tick labels, axis labels and titles have enough + space. See `.Figure.set_tight_layout` for further details. + + If not given, fall back to using the parameters *tight_layout* and + *constrained_layout*, including their config defaults + :rc:`figure.autolayout` and :rc:`figure.constrained_layout.use`. + tight_layout : bool or dict with keys "pad", "w_pad", "h_pad", "rect" or None + If a bool, sets whether to call `.tight_layout` upon drawing. + If ``None``, use :rc:`figure.autolayout` instead. + If a dict, pass it as kwargs to `.tight_layout`, overriding the + default paddings. + constrained_layout : bool or dict with keys "w_pad", "h_pad", "wspace", + "hspace" or None + If a bool, sets whether to call `.constrained_layout` upon drawing. + If ``None``, use :rc:`figure.autolayout` instead. + If a dict, pass it as kwargs to `.constrained_layout`, overriding the + default paddings. """ if ( layout is None and @@ -2475,6 +2528,7 @@ def set_layout(self,layout=None, tight_layout=None, layout = self.get_layout() if layout is not None: + # these will store the state of any warnings we need to pop layout_clash = False bool_conflict = False type_conflict = False @@ -2513,7 +2567,7 @@ def set_layout(self,layout=None, tight_layout=None, if layout_clash: _api.warn_external(f"Figure parameters " f"'layout'=='{layout}' and " - f"'{falselayoutstr}'==True cannot " + f"'{falselayoutstr}'!=False cannot " f"be used together. " f"Please use 'layout' only.") if bool_conflict: @@ -2530,7 +2584,11 @@ def set_layout(self,layout=None, tight_layout=None, f"not True or a dictionary of " f"{layoutstr} arguments. " f"Please use 'layout' only.") - + else: + #layout is None + if all([tight_layout, constrained_layout]): + raise ValueError("Cannot set 'tight_layout' and " + "'constrained_layout' simultaneously.") self._constrained = False self.set_tight_layout(tight_layout) self.set_constrained_layout(constrained_layout) diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index f23bbf77b8fe..ea5639901607 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -544,10 +544,32 @@ def test_valid_layouts(): assert not fig.get_tight_layout() assert fig.get_constrained_layout() - fig = Figure(constrained_layout = {'pad':1}) + fig = Figure(tight_layout = {'pad':1}) + assert fig.get_tight_layout() + assert not fig.get_constrained_layout() + + fig = Figure(constrained_layout = {'w_pad':1}) assert not fig.get_tight_layout() assert fig.get_constrained_layout() + + + fig = Figure(layout='tight', tight_layout = {'pad':1}) + assert fig.get_tight_layout() + assert not fig.get_constrained_layout() + + fig = Figure(layout = 'constrained', constrained_layout = {'w_pad':1}) + assert not fig.get_tight_layout() + assert fig.get_constrained_layout() + + fig = Figure(layout='tight', tight_layout = {'pad':1}, + constrained_layout=False) + assert fig.get_tight_layout() + assert not fig.get_constrained_layout() + fig = Figure(layout = 'constrained', constrained_layout = {'w_pad':1}, + tight_layout=False) + assert not fig.get_tight_layout() + assert fig.get_constrained_layout() def test_invalid_layouts(): @@ -583,15 +605,66 @@ def assert_neither(fig): assert_is_constrained(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='tight' and 'constrained_layout'==True cannot"): + "'layout'=='tight' and 'constrained_layout'!=False cannot"): fig = Figure(layout='tight', constrained_layout=True) assert_is_tight(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='constrained' and 'tight_layout'==True cannot"): + "'layout'=='constrained' and 'tight_layout'!=False cannot"): fig = Figure(layout='constrained', tight_layout=True) assert_is_constrained(fig) + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='tight' and 'constrained_layout'!=False cannot"): + fig = Figure(layout='tight', tight_layout = True, + constrained_layout=True) + assert_is_tight(fig) + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='tight' and 'constrained_layout'!=False cannot"): + fig = Figure(layout='tight', tight_layout ={'pad':1}, + constrained_layout=True) + assert_is_tight(fig) + + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='tight' and 'constrained_layout'!=False cannot"): + fig = Figure(layout='tight', tight_layout ={'pad':1}, + constrained_layout={'w_pad':1}) + assert_is_tight(fig) + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='tight' and 'constrained_layout'!=False cannot"): + fig = Figure(layout='tight', tight_layout = True, + constrained_layout={'w_pad':1}) + assert_is_tight(fig) + + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='constrained' and 'tight_layout'!=False cannot"): + fig = Figure(layout='constrained', constrained_layout=True, + tight_layout=True) + assert_is_constrained(fig) + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='constrained' and 'tight_layout'!=False cannot"): + fig = Figure(layout='constrained', constrained_layout={'w_pad':1}, + tight_layout=True) + assert_is_constrained(fig) + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='constrained' and 'tight_layout'!=False cannot"): + fig = Figure(layout='constrained', constrained_layout={'w_pad':1}, + tight_layout={'pad':1}) + assert_is_constrained(fig) + + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='constrained' and 'tight_layout'!=False cannot"): + fig = Figure(layout='constrained', constrained_layout=True, + tight_layout={'pad':1}) + assert_is_constrained(fig) + with pytest.warns(Warning) as warninfo: fig = Figure(layout='tight', tight_layout=False, @@ -602,7 +675,7 @@ def assert_neither(fig): "and 'tight_layout'==False cannot be used together. " "Please use 'layout' only."), (UserWarning,"Figure parameters 'layout'=='tight' " - "and 'constrained_layout'==True cannot be used together. " + "and 'constrained_layout'!=False cannot be used together. " "Please use 'layout' only.")} assert_is_tight(fig) assert warns==expected @@ -613,7 +686,7 @@ def assert_neither(fig): warns = {(warn.category, warn.message.args[0]) for warn in warninfo} expected = { (UserWarning, "Figure parameters 'layout'=='constrained' " - "and 'tight_layout'==True cannot be used together. " + "and 'tight_layout'!=False cannot be used together. " "Please use 'layout' only."), (UserWarning,"Figure parameters 'layout'=='constrained' " "and 'constrained_layout'==False cannot be used together. " @@ -639,15 +712,24 @@ def assert_neither(fig): assert_is_constrained(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='tight' and 'constrained_layout'==True cannot"): + "'layout'=='tight' and 'constrained_layout'!=False cannot"): fig.set_layout(layout='tight', constrained_layout=True) assert_is_tight(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='constrained' and 'tight_layout'==True cannot"): + "'layout'=='constrained' and 'tight_layout'!=False cannot"): fig.set_layout(layout='constrained', tight_layout=True) assert_is_constrained(fig) + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='tight' and 'constrained_layout'!=False cannot"): + fig.set_layout(layout='tight', constrained_layout={'pad':1}) + assert_is_tight(fig) + with pytest.warns(UserWarning, match="Figure parameters " + "'layout'=='constrained' and 'tight_layout'!=False cannot"): + fig.set_layout(layout='constrained', tight_layout={'pad':1}) + assert_is_constrained(fig) + with pytest.warns(Warning) as warninfo: fig.set_layout(layout='tight', tight_layout=False, @@ -658,7 +740,7 @@ def assert_neither(fig): "and 'tight_layout'==False cannot be used together. " "Please use 'layout' only."), (UserWarning,"Figure parameters 'layout'=='tight' " - "and 'constrained_layout'==True cannot be used together. " + "and 'constrained_layout'!=False cannot be used together. " "Please use 'layout' only.")} assert_is_tight(fig) assert warns==expected @@ -669,13 +751,19 @@ def assert_neither(fig): warns = {(warn.category, warn.message.args[0]) for warn in warninfo} expected = { (UserWarning, "Figure parameters 'layout'=='constrained' " - "and 'tight_layout'==True cannot be used together. " + "and 'tight_layout'!=False cannot be used together. " "Please use 'layout' only."), (UserWarning,"Figure parameters 'layout'=='constrained' " "and 'constrained_layout'==False cannot be used together. " "Please use 'layout' only.")} assert_is_constrained(fig) assert warns==expected + + with pytest.raises(ValueError, + match="Cannot set 'tight_layout' and " + "'constrained_layout' simultaneously."): + fig = Figure(tight_layout = {'w':1},constrained_layout = {'w_pad':1}) + def test_set_subplotpars(): subplotparams_keys = ["left", "bottom", "right", "top", "wspace", "hspace"] fig = plt.figure() From 55d715c072d4ef66f619986d55efc9c8b83e780c Mon Sep 17 00:00:00 2001 From: Jay Stanley Date: Fri, 5 Nov 2021 17:27:29 -0500 Subject: [PATCH 4/7] doc refinements, more tests --- lib/matplotlib/figure.py | 61 ++++++++++++++--------------- lib/matplotlib/tests/test_figure.py | 31 +++++++++++++-- 2 files changed, 58 insertions(+), 34 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index f6a44b37b0d8..b4b11fa499c8 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1212,20 +1212,19 @@ def subplots_adjust(self, left=None, bottom=None, right=None, top=None, def set_subplotpars(self, subplotparams = {}): """ Set the subplot layout parameters. - Accepts either a SubplotParams object, from which the relevant + 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 + `matplotlib.figure.Figure.subplots_adjust` Parameters ---------- - subplotparams : `~matplotlib.figure.SubplotParams` or dict, optional + 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, i.e., a dictionary with - any of ["left", "bottom", "right", 'top", "wspace", "hspace"] as its - keys. + of SubplotParams constructor arguments. By default, an empty dictionary is passed, which maintains the - current state of the figure's SubplotParams + current state of the figure's `.SubplotParams` See Also -------- @@ -1257,7 +1256,7 @@ def set_subplotpars(self, subplotparams = {}): def get_subplotpars(self): """ - Return the SubplotParams object associated with the Figure. + Return the `.SubplotParams` object associated with the Figure. Returns ------- @@ -2470,21 +2469,23 @@ def set_layout(self,layout=None, tight_layout=None, constrained_layout=None): """ Set the figure layout specification. (Optionally) sets how - `.tight_layout` or `.constrained_layout` is called when a dict is - provided to tight_layout or constrained_layout. + `.tight_layout` or `.set_constrained_layout` is used when a dict is + provided to *tight_layout* or *constrained_layout*. - If `layout` is not None, the layout solver is determined exclusively by - `layout`, regardless of `tight_layout` or `constrained_layout`, - but optional padding parameters stored in `tight_layout` or - `constrained_layout` are used with the respective layout. For instance, - if `layout`=='tight', 'tight_layout==False', and `constrained_layout`== - True, `tight_layout` with default paddings is used to format the figure. - If `layout`=='constrained', `tight_layout`=={'pad':1}, and - `constrained_layout`=={'w_pad':1}, then - `.constrained_layout` is called with padding parameters {'w_pad':1}. - If `layout` is None, `tight_layout` and `constrained_layout` are - mutually exclusive. That is, only one can be True or a dict. + If *layout* is not *None*, the layout solver is determined exclusively by + *layout*, regardless of *tight_layout* or *constrained_layout*, + but optional padding parameters stored in *tight_layout* or + *constrained_layout* are used with the respective layout. For instance, + if *layout* is *'tight'*, *tight_layout* is *False*, and + *constrained_layout* is *True*, `.tight_layout` with default paddings + is used to format the figure. + If *layout* is *'constrained'*, *tight_layout* is *{'pad':1}*, and + *constrained_layout* is *{'w_pad':1}*, then + `.set_constrained_layout` is called with padding parameters {'w_pad':1}. + If *layout* is None, *tight_layout* and *constrained_layout* are + mutually exclusive. That is, only one can be True or a dict, as + resolving the case where both are True is ambiguous. Parameters ---------- @@ -2508,16 +2509,17 @@ def set_layout(self,layout=None, tight_layout=None, If not given, fall back to using the parameters *tight_layout* and *constrained_layout*, including their config defaults :rc:`figure.autolayout` and :rc:`figure.constrained_layout.use`. - tight_layout : bool or dict with keys "pad", "w_pad", "h_pad", "rect" or None + tight_layout : bool or dict with keys "pad", "w_pad", "h_pad", "rect", \ +or None If a bool, sets whether to call `.tight_layout` upon drawing. If ``None``, use :rc:`figure.autolayout` instead. If a dict, pass it as kwargs to `.tight_layout`, overriding the default paddings. - constrained_layout : bool or dict with keys "w_pad", "h_pad", "wspace", - "hspace" or None - If a bool, sets whether to call `.constrained_layout` upon drawing. + constrained_layout : bool or dict with keys "w_pad", "h_pad", "wspace", \ +"hspace" or None + If a bool, sets whether to use ``constrained_layout`` upon drawing. If ``None``, use :rc:`figure.autolayout` instead. - If a dict, pass it as kwargs to `.constrained_layout`, overriding the + If a dict, pass it as kwargs to `.set_constrained_layout`, overriding the default paddings. """ if ( @@ -2881,7 +2883,7 @@ def get_size_inches(self): def set_figsize(self, w, h = None): """ Set the figure size in inches. - Convenience wrapper for matplotlib.figure.Figure.set_size_inches. + Convenience wrapper for `~matplotlib.figure.Figure.set_size_inches`. Call signatures:: @@ -2895,9 +2897,6 @@ def set_figsize(self, w, h = None): argument) or width. h : float Height in inches. - forward : bool, default: True - If ``True``, the canvas size is automatically updated, e.g., - you can resize the figure window from the shell. See Also -------- @@ -2915,7 +2914,7 @@ def set_figsize(self, w, h = None): def get_figsize(self): """ Return the current size of the figure in inches. - Convenience wrapper for matplotlib.figure.Figure.get_size_inches. + Convenience wrapper for `~matplotlib.figure.Figure.get_size_inches`. Returns ------- diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index ea5639901607..abf90ca366b8 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -548,10 +548,25 @@ def test_valid_layouts(): assert fig.get_tight_layout() assert not fig.get_constrained_layout() + fig = Figure(tight_layout = True) + assert fig.get_tight_layout() + assert not fig.get_constrained_layout() + + fig = Figure(tight_layout = True, constrained_layout=False) + assert fig.get_tight_layout() + assert not fig.get_constrained_layout() + fig = Figure(constrained_layout = {'w_pad':1}) assert not fig.get_tight_layout() assert fig.get_constrained_layout() + fig = Figure(constrained_layout = True) + assert not fig.get_tight_layout() + assert fig.get_constrained_layout() + + fig = Figure(constrained_layout = True,tight_layout=False) + assert not fig.get_tight_layout() + assert fig.get_constrained_layout() fig = Figure(layout='tight', tight_layout = {'pad':1}) assert fig.get_tight_layout() @@ -565,12 +580,15 @@ def test_valid_layouts(): constrained_layout=False) assert fig.get_tight_layout() assert not fig.get_constrained_layout() - + fig = Figure(layout = 'constrained', constrained_layout = {'w_pad':1}, tight_layout=False) assert not fig.get_tight_layout() assert fig.get_constrained_layout() - + fig = Figure(layout = None, constrained_layout = False, + tight_layout=False) + assert not fig.get_tight_layout() + assert not fig.get_constrained_layout() def test_invalid_layouts(): def assert_is_tight(fig): @@ -763,7 +781,14 @@ def assert_neither(fig): match="Cannot set 'tight_layout' and " "'constrained_layout' simultaneously."): fig = Figure(tight_layout = {'w':1},constrained_layout = {'w_pad':1}) - + with pytest.raises(ValueError, + match="Cannot set 'tight_layout' and " + "'constrained_layout' simultaneously."): + fig = Figure(tight_layout = True,constrained_layout = {'w_pad':1}) + with pytest.raises(ValueError, + match="Cannot set 'tight_layout' and " + "'constrained_layout' simultaneously."): + fig = Figure(tight_layout = True,constrained_layout = True) def test_set_subplotpars(): subplotparams_keys = ["left", "bottom", "right", "top", "wspace", "hspace"] fig = plt.figure() From 781d0e82cc7c7b24dce7b9b6032a1caa55617155 Mon Sep 17 00:00:00 2001 From: Jay Stanley Date: Fri, 5 Nov 2021 17:48:11 -0500 Subject: [PATCH 5/7] pep8/flake8 --- lib/matplotlib/figure.py | 148 ++++++++++++++++++++------------------- 1 file changed, 75 insertions(+), 73 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index b4b11fa499c8..f87528d61db8 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -183,6 +183,7 @@ class FigureBase(Artist): Base class for `.figure.Figure` and `.figure.SubFigure` containing the methods that add artists to the figure or subfigure, create Axes, etc. """ + def __init__(self, **kwargs): super().__init__() # remove the non-figure artist _axes property @@ -1051,9 +1052,9 @@ def legend(self, *args, **kwargs): """ handles, labels, extra_args, kwargs = mlegend._parse_legend_args( - self.axes, - *args, - **kwargs) + self.axes, + *args, + **kwargs) # check for third arg if len(extra_args): # _api.warn_deprecated( @@ -1209,7 +1210,7 @@ def subplots_adjust(self, left=None, bottom=None, right=None, top=None, ax._set_position(ax.get_subplotspec().get_position(self)) self.stale = True - def set_subplotpars(self, subplotparams = {}): + def set_subplotpars(self, subplotparams={}): """ Set the subplot layout parameters. Accepts either a `.SubplotParams` object, from which the relevant @@ -1221,24 +1222,23 @@ def set_subplotpars(self, subplotparams = {}): ---------- 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_subplotpars """ - subplotparams_args = ["left", "bottom", "right", - "top", "wspace", "hspace"] + "top", "wspace", "hspace"] kwargs = {} - if isinstance(subplotparams,SubplotParams): + if isinstance(subplotparams, SubplotParams): for key in subplotparams_args: - kwargs[key] = getattr(subplotparams,key) - elif isinstance(subplotparams,dict): + kwargs[key] = getattr(subplotparams, key) + elif isinstance(subplotparams, dict): for key in subplotparams.keys(): if key in subplotparams_args: kwargs[key] = subplotparams[key] @@ -1248,8 +1248,8 @@ def set_subplotpars(self, subplotparams = {}): " this key was ignored.") else: raise TypeError( - "subplotpars must be a dictionary of keyword-argument pairs or " - "an instance of SubplotParams()") + "subplotpars must be a dictionary of keyword-argument pairs or" + " an instance of SubplotParams()") if kwargs == {}: self.set_subplotpars(self.get_subplotpars()) self.subplots_adjust(**kwargs) @@ -2346,12 +2346,11 @@ def __init__(self, self.subplotpars = subplotpars # constrained_layout: - self._axstack = _AxesStack() # track all figure axes and current axes self.clf() self._cachedRenderer = None - self.set_layout(layout,tight_layout,constrained_layout) + self.set_layout(layout, tight_layout, constrained_layout) # list of child gridspecs for this figure self._gridspecs = [] @@ -2448,7 +2447,7 @@ def layout(self): """ Return the current figure layout solver. """ - if hasattr(self,'_constrained'): + if hasattr(self, '_constrained'): if self.get_constrained_layout(): layout = 'constrained' elif self.get_tight_layout(): @@ -2465,26 +2464,27 @@ def get_layout(self): """ return self.layout - def set_layout(self,layout=None, tight_layout=None, + def set_layout(self, layout=None, tight_layout=None, constrained_layout=None): """ Set the figure layout specification. (Optionally) sets how `.tight_layout` or `.set_constrained_layout` is used when a dict is provided to *tight_layout* or *constrained_layout*. - - If *layout* is not *None*, the layout solver is determined exclusively by - *layout*, regardless of *tight_layout* or *constrained_layout*, + + If *layout* is not *None*, the layout solver is determined exclusively + by *layout*, regardless of *tight_layout* or *constrained_layout*, but optional padding parameters stored in *tight_layout* or *constrained_layout* are used with the respective layout. For instance, - if *layout* is *'tight'*, *tight_layout* is *False*, and - *constrained_layout* is *True*, `.tight_layout` with default paddings + if *layout* is *'tight'*, *tight_layout* is *False*, and + *constrained_layout* is *True*, `.tight_layout` with default paddings is used to format the figure. - If *layout* is *'constrained'*, *tight_layout* is *{'pad':1}*, and + If *layout* is *'constrained'*, *tight_layout* is *{'pad':1}*, and *constrained_layout* is *{'w_pad':1}*, then - `.set_constrained_layout` is called with padding parameters {'w_pad':1}. - If *layout* is None, *tight_layout* and *constrained_layout* are - mutually exclusive. That is, only one can be True or a dict, as + `.set_constrained_layout` is called with padding parameters + *{'w_pad':1}*. + If *layout* is None, *tight_layout* and *constrained_layout* are + mutually exclusive. That is, only one can be True or a dict, as resolving the case where both are True is ambiguous. Parameters @@ -2509,24 +2509,24 @@ def set_layout(self,layout=None, tight_layout=None, If not given, fall back to using the parameters *tight_layout* and *constrained_layout*, including their config defaults :rc:`figure.autolayout` and :rc:`figure.constrained_layout.use`. - tight_layout : bool or dict with keys "pad", "w_pad", "h_pad", "rect", \ -or None + tight_layout : bool or dict with keys "pad", "w_pad", "h_pad", \ +"rect", or None If a bool, sets whether to call `.tight_layout` upon drawing. If ``None``, use :rc:`figure.autolayout` instead. If a dict, pass it as kwargs to `.tight_layout`, overriding the default paddings. - constrained_layout : bool or dict with keys "w_pad", "h_pad", "wspace", \ -"hspace" or None + constrained_layout : bool or dict with keys "w_pad", "h_pad", \ +"wspace", "hspace" or None If a bool, sets whether to use ``constrained_layout`` upon drawing. If ``None``, use :rc:`figure.autolayout` instead. - If a dict, pass it as kwargs to `.set_constrained_layout`, overriding the - default paddings. + If a dict, pass it as kwargs to `.set_constrained_layout`, + overriding the default paddings. """ if ( - layout is None and - tight_layout is None and + layout is None and + tight_layout is None and constrained_layout is None - ): + ): layout = self.get_layout() if layout is not None: @@ -2538,59 +2538,61 @@ def set_layout(self,layout=None, tight_layout=None, if layout == 'constrained': layoutstr = 'constrained_layout' falselayoutstr = 'tight_layout' - layout_clash = tight_layout not in [False,None] - tight_layout=False + layout_clash = tight_layout not in [False, None] + tight_layout = False bool_conflict = ( - isinstance(constrained_layout,bool) and + isinstance(constrained_layout, bool) and not constrained_layout - ) + ) type_conflict = not isinstance(constrained_layout, - (dict, bool, type(None))) - if bool_conflict or type_conflict or constrained_layout is None: - constrained_layout=True - + (dict, bool, type(None))) + if ( + bool_conflict or + type_conflict or + constrained_layout is None + ): + constrained_layout = True elif layout == 'tight': layoutstr = 'tight_layout' falselayoutstr = 'constrained_layout' - layout_clash = constrained_layout not in [False,None] + layout_clash = constrained_layout not in [False, None] constrained_layout = False bool_conflict = ( - isinstance(tight_layout,bool) and + isinstance(tight_layout, bool) and not tight_layout - ) - type_conflict = not isinstance(tight_layout, - (dict, bool, type(None))) + ) + type_conflict = not isinstance(tight_layout, + (dict, bool, type(None))) if bool_conflict or type_conflict or tight_layout is None: - tight_layout=True + tight_layout = True else: _api.check_in_list(['constrained', 'tight'], layout=layout) if layout_clash: - _api.warn_external(f"Figure parameters " - f"'layout'=='{layout}' and " - f"'{falselayoutstr}'!=False cannot " - f"be used together. " - f"Please use 'layout' only.") + _api.warn_external(f"Figure parameters " + f"'layout'=='{layout}' and " + f"'{falselayoutstr}'!=False cannot " + f"be used together. " + f"Please use 'layout' only.") if bool_conflict: _api.warn_external(f"Figure parameters " - f"'layout'=='{layout}' and " - f"'{layoutstr}'==False cannot be " - f"used together. " - f"Please use 'layout' only.") + f"'layout'=='{layout}' and " + f"'{layoutstr}'==False cannot be " + f"used together. " + f"Please use 'layout' only.") if type_conflict: _api.warn_external(f"Figure parameters " - f"'layout'=='{layout}' and " - f"'{layoutstr}' cannot be " - f"used together if '{layoutstr}' is " - f"not True or a dictionary of " - f"{layoutstr} arguments. " - f"Please use 'layout' only.") + f"'layout'=='{layout}' and " + f"'{layoutstr}' cannot be " + f"used together if '{layoutstr}' is " + f"not True or a dictionary of " + f"{layoutstr} arguments. " + f"Please use 'layout' only.") else: - #layout is None if all([tight_layout, constrained_layout]): raise ValueError("Cannot set 'tight_layout' and " - "'constrained_layout' simultaneously.") + "'constrained_layout' simultaneously.") self._constrained = False self.set_tight_layout(tight_layout) self.set_constrained_layout(constrained_layout) @@ -2599,7 +2601,7 @@ def get_tight_layout(self): """Return whether `.tight_layout` is called when drawing.""" return self._tight - def set_tight_layout(self, tight = None): + def set_tight_layout(self, tight=None): """ Set whether and how `.tight_layout` is called when drawing. @@ -2625,7 +2627,7 @@ def get_constrained_layout(self): """ return self._constrained - def set_constrained_layout(self, constrained = None): + def set_constrained_layout(self, constrained=None): """ Set whether ``constrained_layout`` is used upon drawing. If None, :rc:`figure.constrained_layout.use` value will be used. @@ -2880,7 +2882,7 @@ def get_size_inches(self): """ return np.array(self.bbox_inches.p1) - def set_figsize(self, w, h = None): + def set_figsize(self, w, h=None): """ Set the figure size in inches. Convenience wrapper for `~matplotlib.figure.Figure.set_size_inches`. @@ -2909,11 +2911,11 @@ def set_figsize(self, w, h = None): ----- To transform from pixels to inches divide by `Figure.dpi`. """ - self.set_size_inches(w,h) + self.set_size_inches(w, h) def get_figsize(self): """ - Return the current size of the figure in inches. + Return the current size of the figure in inches. Convenience wrapper for `~matplotlib.figure.Figure.get_size_inches`. Returns From 09b931bc029ca4d5c54aa89ed061309492240f8a Mon Sep 17 00:00:00 2001 From: Jay Stanley Date: Fri, 5 Nov 2021 18:12:39 -0500 Subject: [PATCH 6/7] doc formatting --- lib/matplotlib/figure.py | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index f87528d61db8..ed690d74400f 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -2472,20 +2472,26 @@ def set_layout(self, layout=None, tight_layout=None, provided to *tight_layout* or *constrained_layout*. - If *layout* is not *None*, the layout solver is determined exclusively - by *layout*, regardless of *tight_layout* or *constrained_layout*, - but optional padding parameters stored in *tight_layout* or - *constrained_layout* are used with the respective layout. For instance, - if *layout* is *'tight'*, *tight_layout* is *False*, and - *constrained_layout* is *True*, `.tight_layout` with default paddings - is used to format the figure. - If *layout* is *'constrained'*, *tight_layout* is *{'pad':1}*, and - *constrained_layout* is *{'w_pad':1}*, then - `.set_constrained_layout` is called with padding parameters - *{'w_pad':1}*. - If *layout* is None, *tight_layout* and *constrained_layout* are - mutually exclusive. That is, only one can be True or a dict, as - resolving the case where both are True is ambiguous. + - If *layout* is not *None*, the layout solver is determined + exclusively by *layout*, regardless of *tight_layout* or + *constrained_layout*, but optional padding parameters stored in + *tight_layout* or *constrained_layout* are used with the respective + layout. + For instance: + + - if *layout* is *'tight'*, *tight_layout* is *False*, and + *constrained_layout* is *True*, `.tight_layout` with default paddings + is used to format the figure. + + - If *layout* is *'constrained'*, *tight_layout* is *{'pad':1}*, and + *constrained_layout* is *{'w_pad':1}*, then + `.set_constrained_layout` is called with padding parameters + *{'w_pad':1}*. + + - If *layout* is None, *tight_layout* and *constrained_layout* are + mutually exclusive. That is, only one can be *True* or a dict, as + resolving the case where both are not *False* and *layout* is *None* + is ambiguous. Parameters ---------- From 1d324c487d5a625d2b79d04c6caa54dcd8b2c675 Mon Sep 17 00:00:00 2001 From: Jay Stanley Date: Mon, 8 Nov 2021 10:46:47 -0600 Subject: [PATCH 7/7] pep8/flake8 tests. cbook._define_aliases for figsize --- lib/matplotlib/figure.py | 69 +------- lib/matplotlib/tests/test_figure.py | 260 +++++++++++++++------------- 2 files changed, 149 insertions(+), 180 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index ed690d74400f..b9a789d57c93 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -2180,6 +2180,9 @@ def draw(self, renderer): @docstring.interpd +@cbook._define_aliases({ + "size_inches": ["figsize"] +}) class Figure(FigureBase): """ The top level container for all the plot elements. @@ -2472,11 +2475,11 @@ def set_layout(self, layout=None, tight_layout=None, provided to *tight_layout* or *constrained_layout*. - - If *layout* is not *None*, the layout solver is determined - exclusively by *layout*, regardless of *tight_layout* or - *constrained_layout*, but optional padding parameters stored in - *tight_layout* or *constrained_layout* are used with the respective - layout. + - If *layout* is not *None*, the layout solver is determined + exclusively by *layout*, regardless of *tight_layout* or + *constrained_layout*, but optional padding parameters stored in + *tight_layout* or *constrained_layout* are used with the respective + layout. For instance: - if *layout* is *'tight'*, *tight_layout* is *False*, and @@ -2556,7 +2559,7 @@ def set_layout(self, layout=None, tight_layout=None, bool_conflict or type_conflict or constrained_layout is None - ): + ): constrained_layout = True elif layout == 'tight': @@ -2888,60 +2891,6 @@ def get_size_inches(self): """ return np.array(self.bbox_inches.p1) - def set_figsize(self, w, h=None): - """ - Set the figure size in inches. - Convenience wrapper for `~matplotlib.figure.Figure.set_size_inches`. - - Call signatures:: - - fig.set_figsize(w, h) # OR - fig.set_figsize((w, h)) - - Parameters - ---------- - w : (float, float) or float - Width and height in inches (if height not specified as a separate - argument) or width. - h : float - Height in inches. - - See Also - -------- - matplotlib.figure.Figure.get_figsize - matplotlib.figure.Figure.set_size_inches - matplotlib.figure.Figure.set_figwidth - matplotlib.figure.Figure.set_figheight - - Notes - ----- - To transform from pixels to inches divide by `Figure.dpi`. - """ - self.set_size_inches(w, h) - - def get_figsize(self): - """ - Return the current size of the figure in inches. - Convenience wrapper for `~matplotlib.figure.Figure.get_size_inches`. - - Returns - ------- - ndarray - The size (width, height) of the figure in inches. - - See Also - -------- - matplotlib.figure.Figure.set_figsize - matplotlib.figure.Figure.get_size_inches - matplotlib.figure.Figure.get_figwidth - matplotlib.figure.Figure.get_figheight - - Notes - ----- - The size in pixels can be obtained by multiplying with `Figure.dpi`. - """ - return self.get_size_inches() - def get_figwidth(self): """Return the figure width in inches.""" return self.bbox_inches.width diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index abf90ca366b8..7dbd017cb668 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -351,7 +351,7 @@ def test_set_fig_size(): assert fig.get_figwidth() == 1 assert fig.get_figheight() == 3 - fig.set_figsize(2,4) + fig.set_figsize(2, 4) assert fig.get_figsize()[0] == 2 assert fig.get_figsize()[1] == 4 @@ -544,61 +544,65 @@ def test_valid_layouts(): assert not fig.get_tight_layout() assert fig.get_constrained_layout() - fig = Figure(tight_layout = {'pad':1}) + fig = Figure(tight_layout={'pad': 1}) assert fig.get_tight_layout() assert not fig.get_constrained_layout() - fig = Figure(tight_layout = True) + fig = Figure(tight_layout=True) assert fig.get_tight_layout() assert not fig.get_constrained_layout() - fig = Figure(tight_layout = True, constrained_layout=False) + fig = Figure(tight_layout=True, constrained_layout=False) assert fig.get_tight_layout() assert not fig.get_constrained_layout() - fig = Figure(constrained_layout = {'w_pad':1}) + fig = Figure(constrained_layout={'w_pad': 1}) assert not fig.get_tight_layout() assert fig.get_constrained_layout() - fig = Figure(constrained_layout = True) + fig = Figure(constrained_layout=True) assert not fig.get_tight_layout() assert fig.get_constrained_layout() - fig = Figure(constrained_layout = True,tight_layout=False) + fig = Figure(constrained_layout=True, tight_layout=False) assert not fig.get_tight_layout() assert fig.get_constrained_layout() - fig = Figure(layout='tight', tight_layout = {'pad':1}) + fig = Figure(layout='tight', tight_layout={'pad': 1}) assert fig.get_tight_layout() assert not fig.get_constrained_layout() - fig = Figure(layout = 'constrained', constrained_layout = {'w_pad':1}) + fig = Figure(layout='constrained', constrained_layout={'w_pad': 1}) assert not fig.get_tight_layout() assert fig.get_constrained_layout() - fig = Figure(layout='tight', tight_layout = {'pad':1}, - constrained_layout=False) + fig = Figure(layout='tight', tight_layout={'pad': 1}, + constrained_layout=False) assert fig.get_tight_layout() - assert not fig.get_constrained_layout() + assert not fig.get_constrained_layout() - fig = Figure(layout = 'constrained', constrained_layout = {'w_pad':1}, - tight_layout=False) + fig = Figure(layout='constrained', constrained_layout={'w_pad': 1}, + tight_layout=False) assert not fig.get_tight_layout() assert fig.get_constrained_layout() - fig = Figure(layout = None, constrained_layout = False, - tight_layout=False) + fig = Figure(layout=None, constrained_layout=False, + tight_layout=False) assert not fig.get_tight_layout() assert not fig.get_constrained_layout() + + def test_invalid_layouts(): def assert_is_tight(fig): assert fig.get_tight_layout() assert not fig.get_constrained_layout() assert fig.layout == 'tight' + def assert_is_constrained(fig): assert not fig.get_tight_layout() assert fig.get_constrained_layout() assert fig.layout == 'constrained' + def assert_neither(fig): assert not fig.get_tight_layout() assert not fig.get_constrained_layout() @@ -612,106 +616,113 @@ def assert_neither(fig): # precedence. # check the set_layout function on figure construction: - with pytest.warns(UserWarning, match="Figure parameters 'layout'=='tight' " - "and 'tight_layout'==False cannot"): + with pytest.warns(UserWarning, match="Figure parameters 'layout'=='tight'" + " and 'tight_layout'==False cannot"): fig = Figure(layout='tight', tight_layout=False) assert_is_tight(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='constrained' and 'constrained_layout'==False cannot"): + "'layout'=='constrained' and " + "'constrained_layout'==False cannot"): fig = Figure(layout='constrained', constrained_layout=False) assert_is_constrained(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='tight' and 'constrained_layout'!=False cannot"): - fig = Figure(layout='tight', constrained_layout=True) + "'layout'=='tight' and " + "'constrained_layout'!=False cannot"): + fig = Figure(layout='tight', constrained_layout=True) assert_is_tight(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='constrained' and 'tight_layout'!=False cannot"): + "'layout'=='constrained' and " + "'tight_layout'!=False cannot"): fig = Figure(layout='constrained', tight_layout=True) assert_is_constrained(fig) - with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='tight' and 'constrained_layout'!=False cannot"): - fig = Figure(layout='tight', tight_layout = True, - constrained_layout=True) + "'layout'=='tight' and " + "'constrained_layout'!=False cannot"): + fig = Figure(layout='tight', tight_layout=True, + constrained_layout=True) assert_is_tight(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='tight' and 'constrained_layout'!=False cannot"): - fig = Figure(layout='tight', tight_layout ={'pad':1}, - constrained_layout=True) + "'layout'=='tight' and " + "'constrained_layout'!=False cannot"): + fig = Figure(layout='tight', tight_layout={'pad': 1}, + constrained_layout=True) assert_is_tight(fig) - with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='tight' and 'constrained_layout'!=False cannot"): - fig = Figure(layout='tight', tight_layout ={'pad':1}, - constrained_layout={'w_pad':1}) + "'layout'=='tight' and " + "'constrained_layout'!=False cannot"): + fig = Figure(layout='tight', tight_layout={'pad': 1}, + constrained_layout={'w_pad': 1}) assert_is_tight(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='tight' and 'constrained_layout'!=False cannot"): - fig = Figure(layout='tight', tight_layout = True, - constrained_layout={'w_pad':1}) + "'layout'=='tight' and " + "'constrained_layout'!=False cannot"): + fig = Figure(layout='tight', tight_layout=True, + constrained_layout={'w_pad': 1}) assert_is_tight(fig) - with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='constrained' and 'tight_layout'!=False cannot"): + "'layout'=='constrained' and " + "'tight_layout'!=False cannot"): fig = Figure(layout='constrained', constrained_layout=True, - tight_layout=True) + tight_layout=True) assert_is_constrained(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='constrained' and 'tight_layout'!=False cannot"): - fig = Figure(layout='constrained', constrained_layout={'w_pad':1}, - tight_layout=True) + "'layout'=='constrained' and " + "'tight_layout'!=False cannot"): + fig = Figure(layout='constrained', constrained_layout={'w_pad': 1}, + tight_layout=True) assert_is_constrained(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='constrained' and 'tight_layout'!=False cannot"): - fig = Figure(layout='constrained', constrained_layout={'w_pad':1}, - tight_layout={'pad':1}) + "'layout'=='constrained' and " + "'tight_layout'!=False cannot"): + fig = Figure(layout='constrained', constrained_layout={'w_pad': 1}, + tight_layout={'pad': 1}) assert_is_constrained(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='constrained' and 'tight_layout'!=False cannot"): + "'layout'=='constrained' and " + "'tight_layout'!=False cannot"): fig = Figure(layout='constrained', constrained_layout=True, - tight_layout={'pad':1}) + tight_layout={'pad': 1}) assert_is_constrained(fig) with pytest.warns(Warning) as warninfo: - fig = Figure(layout='tight', - tight_layout=False, - constrained_layout=True) + fig = Figure(layout='tight', + tight_layout=False, + constrained_layout=True) warns = {(warn.category, warn.message.args[0]) for warn in warninfo} expected = { (UserWarning, "Figure parameters 'layout'=='tight' " - "and 'tight_layout'==False cannot be used together. " - "Please use 'layout' only."), - (UserWarning,"Figure parameters 'layout'=='tight' " - "and 'constrained_layout'!=False cannot be used together. " - "Please use 'layout' only.")} + "and 'tight_layout'==False cannot be used together. " + "Please use 'layout' only."), + (UserWarning, "Figure parameters 'layout'=='tight' " + "and 'constrained_layout'!=False cannot be used together. " + "Please use 'layout' only.")} assert_is_tight(fig) - assert warns==expected + assert warns == expected with pytest.warns(Warning) as warninfo: - fig = Figure(layout='constrained', - tight_layout=True, - constrained_layout=False) + fig = Figure(layout='constrained', + tight_layout=True, + constrained_layout=False) warns = {(warn.category, warn.message.args[0]) for warn in warninfo} expected = { (UserWarning, "Figure parameters 'layout'=='constrained' " - "and 'tight_layout'!=False cannot be used together. " - "Please use 'layout' only."), - (UserWarning,"Figure parameters 'layout'=='constrained' " - "and 'constrained_layout'==False cannot be used together. " - "Please use 'layout' only.")} + "and 'tight_layout'!=False cannot be used together. " + "Please use 'layout' only."), + (UserWarning, "Figure parameters 'layout'=='constrained' " + "and 'constrained_layout'==False cannot be used together. " + "Please use 'layout' only.")} assert_is_constrained(fig) - assert warns==expected - + assert warns == expected with pytest.raises(ValueError, match="'foobar' is not a valid value for layout"): @@ -720,75 +731,82 @@ def assert_neither(fig): fig = Figure(layout='tight') with pytest.warns(UserWarning, match="Figure parameters 'layout'=='tight' " - "and 'tight_layout'==False cannot"): + "and 'tight_layout'==False cannot"): fig.set_layout(layout='tight', tight_layout=False) assert_is_tight(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='constrained' and 'constrained_layout'==False cannot"): + "'layout'=='constrained' and " + "'constrained_layout'==False cannot"): fig.set_layout(layout='constrained', constrained_layout=False) assert_is_constrained(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='tight' and 'constrained_layout'!=False cannot"): - fig.set_layout(layout='tight', constrained_layout=True) + "'layout'=='tight' and " + "'constrained_layout'!=False cannot"): + fig.set_layout(layout='tight', constrained_layout=True) assert_is_tight(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='constrained' and 'tight_layout'!=False cannot"): + "'layout'=='constrained' and " + "'tight_layout'!=False cannot"): fig.set_layout(layout='constrained', tight_layout=True) assert_is_constrained(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='tight' and 'constrained_layout'!=False cannot"): - fig.set_layout(layout='tight', constrained_layout={'pad':1}) + "'layout'=='tight' and " + "'constrained_layout'!=False cannot"): + fig.set_layout(layout='tight', constrained_layout={'pad': 1}) assert_is_tight(fig) with pytest.warns(UserWarning, match="Figure parameters " - "'layout'=='constrained' and 'tight_layout'!=False cannot"): - fig.set_layout(layout='constrained', tight_layout={'pad':1}) + "'layout'=='constrained' and " + "'tight_layout'!=False cannot"): + fig.set_layout(layout='constrained', tight_layout={'pad': 1}) assert_is_constrained(fig) with pytest.warns(Warning) as warninfo: - fig.set_layout(layout='tight', - tight_layout=False, - constrained_layout=True) + fig.set_layout(layout='tight', + tight_layout=False, + constrained_layout=True) warns = {(warn.category, warn.message.args[0]) for warn in warninfo} expected = { (UserWarning, "Figure parameters 'layout'=='tight' " - "and 'tight_layout'==False cannot be used together. " - "Please use 'layout' only."), - (UserWarning,"Figure parameters 'layout'=='tight' " - "and 'constrained_layout'!=False cannot be used together. " - "Please use 'layout' only.")} + "and 'tight_layout'==False cannot be used together. " + "Please use 'layout' only."), + (UserWarning, "Figure parameters 'layout'=='tight' " + "and 'constrained_layout'!=False cannot be used together. " + "Please use 'layout' only.")} assert_is_tight(fig) - assert warns==expected + assert warns == expected with pytest.warns(Warning) as warninfo: - fig.set_layout(layout='constrained', - tight_layout=True, - constrained_layout=False) + fig.set_layout(layout='constrained', + tight_layout=True, + constrained_layout=False) warns = {(warn.category, warn.message.args[0]) for warn in warninfo} expected = { (UserWarning, "Figure parameters 'layout'=='constrained' " - "and 'tight_layout'!=False cannot be used together. " - "Please use 'layout' only."), - (UserWarning,"Figure parameters 'layout'=='constrained' " - "and 'constrained_layout'==False cannot be used together. " - "Please use 'layout' only.")} + "and 'tight_layout'!=False cannot be used together. " + "Please use 'layout' only."), + (UserWarning, "Figure parameters 'layout'=='constrained' " + "and 'constrained_layout'==False cannot be used together. " + "Please use 'layout' only.")} assert_is_constrained(fig) - assert warns==expected + assert warns == expected with pytest.raises(ValueError, match="Cannot set 'tight_layout' and " "'constrained_layout' simultaneously."): - fig = Figure(tight_layout = {'w':1},constrained_layout = {'w_pad':1}) + fig = Figure(tight_layout={'w': 1}, constrained_layout={'w_pad': 1}) with pytest.raises(ValueError, match="Cannot set 'tight_layout' and " "'constrained_layout' simultaneously."): - fig = Figure(tight_layout = True,constrained_layout = {'w_pad':1}) + fig = Figure(tight_layout=True, constrained_layout={'w_pad': 1}) with pytest.raises(ValueError, match="Cannot set 'tight_layout' and " "'constrained_layout' simultaneously."): - fig = Figure(tight_layout = True,constrained_layout = True) + fig = Figure(tight_layout=True, constrained_layout=True) + + def test_set_subplotpars(): subplotparams_keys = ["left", "bottom", "right", "top", "wspace", "hspace"] fig = plt.figure() @@ -796,7 +814,7 @@ def test_set_subplotpars(): test_dict = {} default_dict = {} for key in subplotparams_keys: - attr = getattr(subplotparams,key) + attr = getattr(subplotparams, key) assert attr == mpl.rcParams[f"figure.subplot.{key}"] default_dict[key] = attr test_dict[key] = attr * 2 @@ -809,33 +827,35 @@ def test_set_subplotpars(): fig.set_subplotpars(test_dict) for key, value in test_dict.items(): - assert getattr(fig.get_subplotpars(),key) == value + assert getattr(fig.get_subplotpars(), key) == value test_subplotparams = SubplotParams() fig.set_subplotpars(test_subplotparams) - for key,value in default_dict.items(): - assert getattr(fig.get_subplotpars(),key) == value + for key, value in default_dict.items(): + assert getattr(fig.get_subplotpars(), key) == value fig.set_subplotpars(test_dict) - for key,value in test_dict.items(): - assert getattr(fig.get_subplotpars(),key) == value + for key, value in test_dict.items(): + assert getattr(fig.get_subplotpars(), key) == value test_dict['foo'] = 'bar' - with pytest.warns(UserWarning, - match ="'foo' is not a valid key for set_subplotpars;" - " this key was ignored"): + with pytest.warns(UserWarning, + match="'foo' is not a valid key for set_subplotpars;" + " this key was ignored"): fig.set_subplotpars(test_dict) with pytest.raises(TypeError, - match="subplotpars must be a dictionary of keyword-argument pairs or " - "an instance of SubplotParams()"): + match="subplotpars must be a dictionary of " + "keyword-argument pairs or " + "an instance of SubplotParams()"): fig.set_subplotpars(['foo']) fig.set_subplotpars({}) - with pytest.raises(AttributeError): # test_dict['foo'] = 'bar' - # but fig.get_subplotpars().foo should be invalid - for key,value in test_dict.items(): - assert getattr(fig.get_subplotpars(),key) == value + with pytest.raises(AttributeError): # test_dict['foo'] = 'bar' + # but fig.get_subplotpars().foo should be invalid + for key, value in test_dict.items(): + assert getattr(fig.get_subplotpars(), key) == value + @check_figures_equal(extensions=["png", "pdf"]) def test_add_artist(fig_test, fig_ref): @@ -1267,7 +1287,7 @@ def test_subfigure_tightbbox(): sub = fig.subfigures(1, 2) np.testing.assert_allclose( - fig.get_tightbbox(fig.canvas.get_renderer()).width, 0.1) + fig.get_tightbbox(fig.canvas.get_renderer()).width, 0.1) @image_comparison(['test_subfigure_ss.png'], style='mpl20', @@ -1350,11 +1370,11 @@ def test_subfigure_spanning(): w = 640 h = 480 - np.testing.assert_allclose(sub_figs[0].bbox.min, [0., h * 2/3]) + np.testing.assert_allclose(sub_figs[0].bbox.min, [0., h * 2 / 3]) np.testing.assert_allclose(sub_figs[0].bbox.max, [w / 3, h]) np.testing.assert_allclose(sub_figs[1].bbox.min, [w / 3, h / 3]) - np.testing.assert_allclose(sub_figs[1].bbox.max, [w * 2/3, h]) + np.testing.assert_allclose(sub_figs[1].bbox.max, [w * 2 / 3, h]) np.testing.assert_allclose(sub_figs[2].bbox.min, [w / 3, 0]) np.testing.assert_allclose(sub_figs[2].bbox.max, [w, h / 3]) @@ -1395,7 +1415,7 @@ def test_subfigure_ticks(): @image_comparison(['test_subfigure_scatter_size.png'], style='mpl20', - remove_text=True) + remove_text=True) def test_subfigure_scatter_size(): # markers in the left- and right-most subplots should be the same fig = plt.figure() @@ -1499,12 +1519,12 @@ def test_kwargs_pass(): assert fig.get_label() == 'whole Figure' assert sub_fig.get_label() == 'sub figure' + def test_fig_get_set(): - varnames = filter(lambda var: var not in ['self','kwargs','args'], - Figure.__init__.__code__.co_varnames) + 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}") - + getfunc = getattr(fig, f"get_{var}") + setfunc = getattr(fig, f"set_{var}") pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy