From 7760e5e99f2ea851d168d58f4f502ad3010da6b1 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sat, 3 Dec 2022 10:27:24 -0500 Subject: [PATCH 1/8] MNT: remove explicit label setting This is already done at creation time. --- lib/matplotlib/figure.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 658201672e40..157428f5ddb0 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -2048,9 +2048,7 @@ def _do_layout(gs, mosaic, unique_ids, nested): if sharey: ax.sharey(ax0) ax._label_outer_yaxis(check_patch=True) - for k, ax in ret.items(): - if isinstance(k, str): - ax.set_label(k) + return ret def _set_artist_props(self, a): From f74fe35df8c91b22ae30b1acd3638b690c575e76 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sat, 3 Dec 2022 09:23:14 -0500 Subject: [PATCH 2/8] ENH: add ability to pass per-Axes subplot_kw through subplot_mosaic --- .../next_whats_new/per_subplot_mosaic.rst | 22 +++++++ lib/matplotlib/figure.py | 63 +++++++++++++++++-- lib/matplotlib/pyplot.py | 6 +- lib/matplotlib/tests/test_figure.py | 48 +++++++++++++- tutorials/provisional/mosaic.py | 63 ++++++++++++++++++- 5 files changed, 192 insertions(+), 10 deletions(-) create mode 100644 doc/users/next_whats_new/per_subplot_mosaic.rst diff --git a/doc/users/next_whats_new/per_subplot_mosaic.rst b/doc/users/next_whats_new/per_subplot_mosaic.rst new file mode 100644 index 000000000000..f78cef3996ad --- /dev/null +++ b/doc/users/next_whats_new/per_subplot_mosaic.rst @@ -0,0 +1,22 @@ +Per-subplot keyword arguments in ``subplot_mosaic`` +---------------------------------------------------- + +It is now possible to pass keyword arguments through to the creation to each +specific call to ``add_subplot`` in `.Figure.subplot_mosaic` and +`.pyplot.subplot_mosaic` : + +.. plot:: + :include-source: true + + fig, axd = plt.subplot_mosaic( + "AB;CD", + per_subplot_kw={ + "A": {"projection": "polar"}, + ("C", "D"): {"xscale": "log"}, + "B": {"projection": "3d"}, + }, + ) + + +This is particularly useful for creating mosaics with mixed projections, but +any keyword arguments can be passed through. diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 157428f5ddb0..c0c156449413 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1759,6 +1759,25 @@ def get_tightbbox(self, renderer=None, bbox_extra_artists=None): return _bbox + @staticmethod + def _norm_per_subplot_kw(per_subplot_kw): + expanded = {} + for k, v in per_subplot_kw.items(): + if isinstance(k, tuple): + for sub_key in k: + if sub_key in expanded: + raise ValueError( + f'The key {sub_key!r} appears multiple times.' + ) + expanded[sub_key] = v + else: + if k in expanded: + raise ValueError( + f'The key {k!r} appears multiple times.' + ) + expanded[k] = v + return expanded + @staticmethod def _normalize_grid_string(layout): if '\n' not in layout: @@ -1771,7 +1790,8 @@ def _normalize_grid_string(layout): def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False, width_ratios=None, height_ratios=None, - empty_sentinel='.', subplot_kw=None, gridspec_kw=None): + empty_sentinel='.', subplot_kw=None, gridspec_kw=None, + per_subplot_kw=None): """ Build a layout of Axes based on ASCII art or nested lists. @@ -1821,6 +1841,9 @@ def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False, The string notation allows only single character Axes labels and does not support nesting but is very terse. + Tuples may be used instead of lists and tuples may not be used + as Axes identifiers. + sharex, sharey : bool, default: False If True, the x-axis (*sharex*) or y-axis (*sharey*) will be shared among all subplots. In that case, tick label visibility and axis @@ -1843,7 +1866,21 @@ def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False, subplot_kw : dict, optional Dictionary with keywords passed to the `.Figure.add_subplot` call - used to create each subplot. + used to create each subplot. These values may be overridden by + values in *per_subplot_kw*. + + per_subplot_kw : dict, optional + A dictionary mapping the Axes idenitfies or tuples of identifies to + a dictionary of keyword arguments to be passed to the + `.Figure.add_subplot` call used to create each subplot. The values + in these dictionaries have precedence over the values in + *subplot_kw*. + + In the special case *mosaic* being a string, multi-character keys + in *per_subplot_kw* will be applied to all of the Axes named + treating the string as a sequence. + + .. versionadded:: 3.7 gridspec_kw : dict, optional Dictionary with keywords passed to the `.GridSpec` constructor used @@ -1868,6 +1905,8 @@ def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False, """ subplot_kw = subplot_kw or {} gridspec_kw = dict(gridspec_kw or {}) + per_subplot_kw = per_subplot_kw or {} + if height_ratios is not None: if 'height_ratios' in gridspec_kw: raise ValueError("'height_ratios' must not be defined both as " @@ -1882,6 +1921,14 @@ def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False, # special-case string input if isinstance(mosaic, str): mosaic = self._normalize_grid_string(mosaic) + per_subplot_kw = { + tuple(k): v for k, v in per_subplot_kw.items() + } + + per_subplot_kw = self._norm_per_subplot_kw( + per_subplot_kw + ) + # Only accept strict bools to allow a possible future API expansion. _api.check_isinstance(bool, sharex=sharex, sharey=sharey) @@ -2011,7 +2058,11 @@ def _do_layout(gs, mosaic, unique_ids, nested): raise ValueError(f"There are duplicate keys {name} " f"in the layout\n{mosaic!r}") ax = self.add_subplot( - gs[slc], **{'label': str(name), **subplot_kw} + gs[slc], **{ + 'label': str(name), + **subplot_kw, + **per_subplot_kw.get(name, {}) + } ) output[name] = ax elif method == 'nested': @@ -2048,7 +2099,11 @@ def _do_layout(gs, mosaic, unique_ids, nested): if sharey: ax.sharey(ax0) ax._label_outer_yaxis(check_patch=True) - + if extra := set(per_subplot_kw) - set(ret): + raise ValueError( + f"The keys {extra} are in *per_subplot_kw* " + "but not in the mosaic." + ) return ret def _set_artist_props(self, a): diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 25c1f43d5f33..2dfac1bf9deb 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -1479,7 +1479,8 @@ def subplots(nrows=1, ncols=1, *, sharex=False, sharey=False, squeeze=True, def subplot_mosaic(mosaic, *, sharex=False, sharey=False, width_ratios=None, height_ratios=None, empty_sentinel='.', - subplot_kw=None, gridspec_kw=None, **fig_kw): + subplot_kw=None, gridspec_kw=None, + per_subplot_kw=None, **fig_kw): """ Build a layout of Axes based on ASCII art or nested lists. @@ -1576,7 +1577,8 @@ def subplot_mosaic(mosaic, *, sharex=False, sharey=False, mosaic, sharex=sharex, sharey=sharey, height_ratios=height_ratios, width_ratios=width_ratios, subplot_kw=subplot_kw, gridspec_kw=gridspec_kw, - empty_sentinel=empty_sentinel + empty_sentinel=empty_sentinel, + per_subplot_kw=per_subplot_kw, ) return fig, ax_dict diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index ee07cadef78b..065e0f728536 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -848,7 +848,12 @@ def test_animated_with_canvas_change(fig_test, fig_ref): class TestSubplotMosaic: @check_figures_equal(extensions=["png"]) @pytest.mark.parametrize( - "x", [[["A", "A", "B"], ["C", "D", "B"]], [[1, 1, 2], [3, 4, 2]]] + "x", [ + [["A", "A", "B"], ["C", "D", "B"]], + [[1, 1, 2], [3, 4, 2]], + (("A", "A", "B"), ("C", "D", "B")), + ((1, 1, 2), (3, 4, 2)) + ] ) def test_basic(self, fig_test, fig_ref, x): grid_axes = fig_test.subplot_mosaic(x) @@ -998,6 +1003,10 @@ def test_fail_list_of_str(self): plt.subplot_mosaic(['foo', 'bar']) with pytest.raises(ValueError, match='must be 2D'): plt.subplot_mosaic(['foo']) + with pytest.raises(ValueError, match='must be 2D'): + plt.subplot_mosaic([['foo', ('bar',)]]) + with pytest.raises(ValueError, match='must be 2D'): + plt.subplot_mosaic([['a', 'b'], [('a', 'b'), 'c']]) @check_figures_equal(extensions=["png"]) @pytest.mark.parametrize("subplot_kw", [{}, {"projection": "polar"}, None]) @@ -1011,8 +1020,26 @@ def test_subplot_kw(self, fig_test, fig_ref, subplot_kw): axB = fig_ref.add_subplot(gs[0, 1], **subplot_kw) + @check_figures_equal(extensions=["png"]) + @pytest.mark.parametrize("multi_value", ['BC', tuple('BC')]) + def test_per_subplot_kw(self, fig_test, fig_ref, multi_value): + x = 'AB;CD' + grid_axes = fig_test.subplot_mosaic( + x, + subplot_kw={'facecolor': 'red'}, + per_subplot_kw={ + 'D': {'facecolor': 'blue'}, + multi_value: {'facecolor': 'green'}, + } + ) + + gs = fig_ref.add_gridspec(2, 2) + for color, spec in zip(['red', 'green', 'green', 'blue'], gs): + fig_ref.add_subplot(spec, facecolor=color) + def test_string_parser(self): normalize = Figure._normalize_grid_string + assert normalize('ABC') == [['A', 'B', 'C']] assert normalize('AB;CC') == [['A', 'B'], ['C', 'C']] assert normalize('AB;CC;DE') == [['A', 'B'], ['C', 'C'], ['D', 'E']] @@ -1029,6 +1056,25 @@ def test_string_parser(self): DE """) == [['A', 'B'], ['C', 'C'], ['D', 'E']] + def test_per_subplot_kw_expander(self): + normalize = Figure._norm_per_subplot_kw + assert normalize({"A": {}, "B": {}}) == {"A": {}, "B": {}} + assert normalize({("A", "B"): {}}) == {"A": {}, "B": {}} + with pytest.raises( + ValueError, match=f'The key {"B"!r} appears multiple times' + ): + normalize({("A", "B"): {}, "B": {}}) + with pytest.raises( + ValueError, match=f'The key {"B"!r} appears multiple times' + ): + normalize({"B": {}, ("A", "B"): {}}) + + def test_extra_per_subplot_kw(self): + with pytest.raises( + ValueError, match=f'The keys {set("B")!r} are in' + ): + Figure().subplot_mosaic("A", per_subplot_kw={"B": {}}) + @check_figures_equal(extensions=["png"]) @pytest.mark.parametrize("str_pattern", ["AAA\nBBB", "\nAAA\nBBB\n", "ABC\nDEF"] diff --git a/tutorials/provisional/mosaic.py b/tutorials/provisional/mosaic.py index 862ef71b4289..ef93c5fdf572 100644 --- a/tutorials/provisional/mosaic.py +++ b/tutorials/provisional/mosaic.py @@ -202,8 +202,8 @@ def identify_axes(ax_dict, fontsize=48): # empty sentinel with the string shorthand because it may be stripped # while processing the input. # -# Controlling mosaic and subplot creation -# ======================================= +# Controlling mosaic creation +# =========================== # # This feature is built on top of `.gridspec` and you can pass the # keyword arguments through to the underlying `.gridspec.GridSpec` @@ -278,8 +278,12 @@ def identify_axes(ax_dict, fontsize=48): ############################################################################### +# Controlling subplot creation +# ============================ + # We can also pass through arguments used to create the subplots -# (again, the same as `.Figure.subplots`). +# (again, the same as `.Figure.subplots`) which will apply to all +# of the Axes created. axd = plt.figure(constrained_layout=True).subplot_mosaic( @@ -287,6 +291,59 @@ def identify_axes(ax_dict, fontsize=48): ) identify_axes(axd) +############################################################################### +# Per-Axes subplot keyword arguments +# ---------------------------------- +# +# +# If you need to control the parameters passed to each subplot individually use +# *per_subplot_kw* to pass a mapping between the Axes identifiers (or +# tuples of Axes identifiers) to dictionaries of keywords to be passed. +# +# .. versionadded:: 3.7 +# + + +fig, axd = plt.subplot_mosaic( + "AB;CD", + per_subplot_kw={ + "A": {"projection": "polar"}, + ("C", "D"): {"xscale": "log"} + }, +) +identify_axes(axd) + +############################################################################### +# If the layout is specified with the string short-hand, then we know the +# Axes labels will be one character and can unambiguously interpret longer +# strings in *per_subplot_kw* to specify a set of Axes to apply the +# keywords to: + + +fig, axd = plt.subplot_mosaic( + "AB;CD", + per_subplot_kw={ + "AD": {"projection": "polar"}, + "BC": {"facecolor": ".9"} + }, +) +identify_axes(axd) + +############################################################################### +# if *subplot_kw* and *per_subplot_kw* are used together, then they are +# merged with *per_subplot_kw* taking priority: + + +axd = plt.figure(constrained_layout=True).subplot_mosaic( + "AB;CD", + subplot_kw={"facecolor": "xkcd:tangerine"}, + per_subplot_kw={ + "B": {"facecolor": "xkcd:water blue"}, + "D": {"projection": "polar", "facecolor": "w"}, + } +) +identify_axes(axd) + ############################################################################### # Nested list input From e651574e9a8bc0c397871174710ef577aeafc628 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Tue, 13 Dec 2022 18:07:11 -0500 Subject: [PATCH 3/8] DOC: clarify special case Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- lib/matplotlib/figure.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index c0c156449413..2436921ea940 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1876,9 +1876,9 @@ def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False, in these dictionaries have precedence over the values in *subplot_kw*. - In the special case *mosaic* being a string, multi-character keys - in *per_subplot_kw* will be applied to all of the Axes named - treating the string as a sequence. + If *mosaic* is a string, and thus all keys are single characters, + it is possible to use a single string instead of a tuple as keys; + i.e. "AB" is equivalent to `("A", "B")`. .. versionadded:: 3.7 From 54189fcadf27bb4ec4223dcf89facdf4863aee9c Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Tue, 13 Dec 2022 18:32:17 -0500 Subject: [PATCH 4/8] DOC: tweak wording on what are allowed keys in the mosaic --- lib/matplotlib/figure.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 2436921ea940..f51f56288d89 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1841,8 +1841,8 @@ def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False, The string notation allows only single character Axes labels and does not support nesting but is very terse. - Tuples may be used instead of lists and tuples may not be used - as Axes identifiers. + The Axes identifiers may be `str` or a non-iterable hashable + object (e.g. `tuple` s may not be used). sharex, sharey : bool, default: False If True, the x-axis (*sharex*) or y-axis (*sharey*) will be shared From 4e3143e4882609b362a350c50d8960adeeec35c5 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Wed, 14 Dec 2022 09:19:41 -0500 Subject: [PATCH 5/8] DOC: fix markup --- 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 f51f56288d89..b520e5e7ae49 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1878,7 +1878,7 @@ def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False, If *mosaic* is a string, and thus all keys are single characters, it is possible to use a single string instead of a tuple as keys; - i.e. "AB" is equivalent to `("A", "B")`. + i.e. ``"AB"`` is equivalent to ``("A", "B")``. .. versionadded:: 3.7 From f714df77930928339bd3f17aa4ebf4340b03797d Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sun, 18 Dec 2022 13:23:04 -0500 Subject: [PATCH 6/8] DOC: fix word choice and markup Co-authored-by: Ruth Comer <10599679+rcomer@users.noreply.github.com> --- lib/matplotlib/figure.py | 2 +- tutorials/provisional/mosaic.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index b520e5e7ae49..b0ebbb80299c 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1870,7 +1870,7 @@ def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False, values in *per_subplot_kw*. per_subplot_kw : dict, optional - A dictionary mapping the Axes idenitfies or tuples of identifies to + A dictionary mapping the Axes identifiers or tuples of identifiers to a dictionary of keyword arguments to be passed to the `.Figure.add_subplot` call used to create each subplot. The values in these dictionaries have precedence over the values in diff --git a/tutorials/provisional/mosaic.py b/tutorials/provisional/mosaic.py index ef93c5fdf572..761570bbf9d9 100644 --- a/tutorials/provisional/mosaic.py +++ b/tutorials/provisional/mosaic.py @@ -280,7 +280,7 @@ def identify_axes(ax_dict, fontsize=48): ############################################################################### # Controlling subplot creation # ============================ - +# # We can also pass through arguments used to create the subplots # (again, the same as `.Figure.subplots`) which will apply to all # of the Axes created. From 5b0fb4aa6c9f2e12a3e30aa732bcbe7cf01ce018 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sun, 18 Dec 2022 13:32:24 -0500 Subject: [PATCH 7/8] DOC: add missing docs to pyplot --- lib/matplotlib/figure.py | 4 ++-- lib/matplotlib/pyplot.py | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index b0ebbb80299c..f6dd88220910 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1870,8 +1870,8 @@ def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False, values in *per_subplot_kw*. per_subplot_kw : dict, optional - A dictionary mapping the Axes identifiers or tuples of identifiers to - a dictionary of keyword arguments to be passed to the + A dictionary mapping the Axes identifiers or tuples of identifiers + to a dictionary of keyword arguments to be passed to the `.Figure.add_subplot` call used to create each subplot. The values in these dictionaries have precedence over the values in *subplot_kw*. diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 2dfac1bf9deb..049c3af356af 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -1551,7 +1551,21 @@ def subplot_mosaic(mosaic, *, sharex=False, sharey=False, subplot_kw : dict, optional Dictionary with keywords passed to the `.Figure.add_subplot` call - used to create each subplot. + used to create each subplot. These values may be overridden by + values in *per_subplot_kw*. + + per_subplot_kw : dict, optional + A dictionary mapping the Axes identifiers or tuples of identifiers + to a dictionary of keyword arguments to be passed to the + `.Figure.add_subplot` call used to create each subplot. The values + in these dictionaries have precedence over the values in + *subplot_kw*. + + If *mosaic* is a string, and thus all keys are single characters, + it is possible to use a single string instead of a tuple as keys; + i.e. ``"AB"`` is equivalent to ``("A", "B")``. + + .. versionadded:: 3.7 gridspec_kw : dict, optional Dictionary with keywords passed to the `.GridSpec` constructor used From e56f876420c445b27cb30038abbc2e102015a693 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 22 Dec 2022 21:55:50 -0500 Subject: [PATCH 8/8] DOC/STY: improve wording and line wrapping Co-authored-by: Elliott Sales de Andrade --- doc/users/next_whats_new/per_subplot_mosaic.rst | 2 +- lib/matplotlib/figure.py | 8 +++----- tutorials/provisional/mosaic.py | 3 +-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/doc/users/next_whats_new/per_subplot_mosaic.rst b/doc/users/next_whats_new/per_subplot_mosaic.rst index f78cef3996ad..bb48bd5e281d 100644 --- a/doc/users/next_whats_new/per_subplot_mosaic.rst +++ b/doc/users/next_whats_new/per_subplot_mosaic.rst @@ -1,7 +1,7 @@ Per-subplot keyword arguments in ``subplot_mosaic`` ---------------------------------------------------- -It is now possible to pass keyword arguments through to the creation to each +It is now possible to pass keyword arguments through to Axes creation in each specific call to ``add_subplot`` in `.Figure.subplot_mosaic` and `.pyplot.subplot_mosaic` : diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index f6dd88220910..bf58f0cae681 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1790,8 +1790,8 @@ def _normalize_grid_string(layout): def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False, width_ratios=None, height_ratios=None, - empty_sentinel='.', subplot_kw=None, gridspec_kw=None, - per_subplot_kw=None): + empty_sentinel='.', + subplot_kw=None, per_subplot_kw=None, gridspec_kw=None): """ Build a layout of Axes based on ASCII art or nested lists. @@ -1925,9 +1925,7 @@ def subplot_mosaic(self, mosaic, *, sharex=False, sharey=False, tuple(k): v for k, v in per_subplot_kw.items() } - per_subplot_kw = self._norm_per_subplot_kw( - per_subplot_kw - ) + per_subplot_kw = self._norm_per_subplot_kw(per_subplot_kw) # Only accept strict bools to allow a possible future API expansion. _api.check_isinstance(bool, sharex=sharex, sharey=sharey) diff --git a/tutorials/provisional/mosaic.py b/tutorials/provisional/mosaic.py index 761570bbf9d9..ac56d5f9f5d7 100644 --- a/tutorials/provisional/mosaic.py +++ b/tutorials/provisional/mosaic.py @@ -295,7 +295,6 @@ def identify_axes(ax_dict, fontsize=48): # Per-Axes subplot keyword arguments # ---------------------------------- # -# # If you need to control the parameters passed to each subplot individually use # *per_subplot_kw* to pass a mapping between the Axes identifiers (or # tuples of Axes identifiers) to dictionaries of keywords to be passed. @@ -330,7 +329,7 @@ def identify_axes(ax_dict, fontsize=48): identify_axes(axd) ############################################################################### -# if *subplot_kw* and *per_subplot_kw* are used together, then they are +# If *subplot_kw* and *per_subplot_kw* are used together, then they are # merged with *per_subplot_kw* taking priority: