diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index e015d0ec94bb..22b4a30eb163 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -335,16 +335,16 @@ def _suplabels(self, t, info, **kwargs): elif info['name'] == '_supylabel': autopos = x is None if x is None: - x = info['x0'] + x = mpl.rcParams[info['x0']] if y is None: - y = info['y0'] + y = mpl.rcParams[info['y0']] if 'horizontalalignment' not in kwargs and 'ha' not in kwargs: - kwargs['horizontalalignment'] = info['ha'] + kwargs['horizontalalignment'] = mpl.rcParams[info['ha']] if 'verticalalignment' not in kwargs and 'va' not in kwargs: - kwargs['verticalalignment'] = info['va'] + kwargs['verticalalignment'] = mpl.rcParams[info['va']] if 'rotation' not in kwargs: - kwargs['rotation'] = info['rotation'] + kwargs['rotation'] = mpl.rcParams[info['rotation']] if 'fontproperties' not in kwargs: if 'fontsize' not in kwargs and 'size' not in kwargs: @@ -370,8 +370,9 @@ def _suplabels(self, t, info, **kwargs): @_docstring.copy(_suplabels) def suptitle(self, t, **kwargs): # docstring from _suplabels... - info = {'name': '_suptitle', 'x0': 0.5, 'y0': 0.98, - 'ha': 'center', 'va': 'top', 'rotation': 0, + info = {'name': '_suptitle', 'x0': 'figure.title_x', + 'y0': 'figure.title_y', 'ha': 'figure.title_ha', + 'va': 'figure.title_va', 'rotation': 'figure.title_rotation', 'size': 'figure.titlesize', 'weight': 'figure.titleweight'} return self._suplabels(t, info, **kwargs) @@ -380,8 +381,9 @@ def suptitle(self, t, **kwargs): @_docstring.copy(_suplabels) def supxlabel(self, t, **kwargs): # docstring from _suplabels... - info = {'name': '_supxlabel', 'x0': 0.5, 'y0': 0.01, - 'ha': 'center', 'va': 'bottom', 'rotation': 0, + info = {'name': '_supxlabel', 'x0': 'figure.xlabel_x', + 'y0': 'figure.xlabel_y', 'ha': 'figure.xlabel_ha', + 'va': 'figure.xlabel_va', 'rotation': 'figure.xlabel_rotation', 'size': 'figure.labelsize', 'weight': 'figure.labelweight'} return self._suplabels(t, info, **kwargs) @@ -390,8 +392,9 @@ def supxlabel(self, t, **kwargs): @_docstring.copy(_suplabels) def supylabel(self, t, **kwargs): # docstring from _suplabels... - info = {'name': '_supylabel', 'x0': 0.02, 'y0': 0.5, - 'ha': 'left', 'va': 'center', 'rotation': 'vertical', + info = {'name': '_supylabel', 'x0': 'figure.ylabel_x', + 'y0': 'figure.ylabel_y', 'ha': 'figure.ylabel_ha', + 'va': 'figure.ylabel_va', 'rotation': 'figure.ylabel_rotation', 'rotation_mode': 'anchor', 'size': 'figure.labelsize', 'weight': 'figure.labelweight'} return self._suplabels(t, info, **kwargs) diff --git a/lib/matplotlib/mpl-data/matplotlibrc b/lib/matplotlib/mpl-data/matplotlibrc index b76b1191eecd..40238ae2429f 100644 --- a/lib/matplotlib/mpl-data/matplotlibrc +++ b/lib/matplotlib/mpl-data/matplotlibrc @@ -553,6 +553,21 @@ ## * FIGURE * ## *************************************************************************** ## See https://matplotlib.org/api/figure_api.html#matplotlib.figure.Figure +#figure.titleloc_x: 0.5 +#figure.titleloc_y: 0.98 +#figure.title_horizontalalignment: center +#figure.title_verticalalignment: top +#figure.title_rotation: 0 +#figure.xlabel_x: 0.5 +#figure.xlabel_y: 0.01 +#figure.xlabel_ha: center +#figure.xlabel_va: bottom +#figure.xlabel_rotation: 0 +#figure.ylabel_x: 0.02 +#figure.ylabel_y: 0.5 +#figure.ylabel_ha: left +#figure.ylabel_va: center +#figure.ylabel_rotation: vertical #figure.titlesize: large # size of the figure title (``Figure.suptitle()``) #figure.titleweight: normal # weight of the figure title #figure.labelsize: large # size of the figure label (``Figure.sup[x|y]label()``) diff --git a/lib/matplotlib/rcsetup.py b/lib/matplotlib/rcsetup.py index 5a5914ba7b3b..d81297d2fcc3 100644 --- a/lib/matplotlib/rcsetup.py +++ b/lib/matplotlib/rcsetup.py @@ -808,6 +808,17 @@ def _convert_validator_spec(key, conv): return conv +def validate_rotation(s): + rotations = ["vertical", "horizontal"] + if isinstance(s, str): + s = s.lower() + if s in rotations: + return s + try: + return float(s) + except ValueError as e: + raise ValueError("%s is not a valid rotation. Valid rotation values " + "are %s." % (s, ", ".join(rotations))) from e # Mapping of rcParams to validators. # Converters given as lists or _ignorecase are converted to ValidateInStrings # immediately below. @@ -1132,6 +1143,22 @@ def _convert_validator_spec(key, conv): "grid.alpha": validate_float, ## figure props + # new props + "figure.title_x": validate_float, + "figure.title_y": validate_float, + "figure.title_ha": ["center", "left", "right"], + "figure.title_va": ["top", "center", "bottom", "baseline"], + "figure.title_rotation": validate_rotation, + "figure.xlabel_x": validate_float, + "figure.xlabel_y": validate_float, + "figure.xlabel_ha": ["center", "left", "right"], + "figure.xlabel_va": ["top", "center", "bottom", "baseline"], + "figure.xlabel_rotation": validate_rotation, + "figure.ylabel_x": validate_float, + "figure.ylabel_y": validate_float, + "figure.ylabel_ha": ["center", "left", "right"], + "figure.ylabel_va": ["top", "center", "bottom", "baseline"], + "figure.ylabel_rotation": validate_rotation, # figure title "figure.titlesize": validate_fontsize, "figure.titleweight": validate_fontweight, diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index e38a772fe81e..c4bce9f4802f 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -1389,13 +1389,31 @@ def test_kwargs_pass(): @check_figures_equal(extensions=["png"]) def test_rcparams(fig_test, fig_ref): - fig_ref.supxlabel("xlabel", weight='bold', size=15) - fig_ref.supylabel("ylabel", weight='bold', size=15) - fig_ref.suptitle("Title", weight='light', size=20) + fig_ref.supxlabel("xlabel", x=0.1, y=0.5, horizontalalignment='left', + va="top", rotation=10, weight='bold', size=15) + fig_ref.supylabel("ylabel", x=0.1, y=0.2, ha="right", va="bottom", + rotation=22.5, weight='bold', size=15) + fig_ref.suptitle("Title", x=0.1, y=0.2, ha="right", va="bottom", + rotation=22.5, weight='light', size=20) with mpl.rc_context({'figure.labelweight': 'bold', 'figure.labelsize': 15, 'figure.titleweight': 'light', - 'figure.titlesize': 20}): + 'figure.titlesize': 20, + 'figure.title_x': 0.1, + 'figure.title_y': 0.2, + 'figure.title_ha': "right", + 'figure.title_va': "bottom", + 'figure.title_rotation': 22.5, + 'figure.xlabel_x': 0.1, + 'figure.xlabel_y': 0.5, + 'figure.xlabel_ha': "left", + 'figure.xlabel_va': "top", + 'figure.xlabel_rotation': 10, + 'figure.ylabel_x': 0.1, + 'figure.ylabel_y': 0.2, + 'figure.ylabel_ha': "right", + 'figure.ylabel_va': "bottom", + 'figure.ylabel_rotation': 22.5}): fig_test.supxlabel("xlabel") fig_test.supylabel("ylabel") fig_test.suptitle("Title")