From d1067a62bba04d22c6379739724c54ec9202403a Mon Sep 17 00:00:00 2001 From: Alex van Diepen Date: Tue, 28 Mar 2023 18:29:09 +0200 Subject: [PATCH 01/12] Used previous pull request and now trying to figure out why savefigure not keeps the title layout --- lib/matplotlib/axes/_base.py | 10 +++++ lib/matplotlib/figure.py | 84 ++++++++++++++++++++++++++++++++++-- 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index df28052e9a57..83d0e4d990c1 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -2990,6 +2990,16 @@ def _update_title_position(self, renderer): x, _ = title.get_position() title.set_position((x, ymax)) + # Align bboxes of grouped axes to highest in group + grouped_axs = self.figure._align_label_groups['title'].get_siblings(self) + bb_ymax = None + ax_max = None + for ax in grouped_axs: + if bb_ymax is None or ax.bbox.ymax > bb_ymax: + bb_ymax = ax.bbox.ymax + ax_max = ax + self.bbox = ax_max.bbox + # Drawing @martist.allow_rasterization def draw(self, renderer): diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index dedd3ecc652f..40bf5a74e97c 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -183,10 +183,10 @@ def __init__(self, **kwargs): self._supxlabel = None self._supylabel = None - # groupers to keep track of x and y labels we want to align. - # see self.align_xlabels and self.align_ylabels and + # groupers to keep track of x, y and title labels we want to align. + # see self.align_xlabels, self.align_ylabels, self.align_titlelabels and # axis._get_tick_boxes_siblings - self._align_label_groups = {"x": cbook.Grouper(), "y": cbook.Grouper()} + self._align_label_groups = {"x": cbook.Grouper(), "y": cbook.Grouper(), "title": cbook.Grouper()} self.figure = self self._localaxes = [] # track all axes @@ -1327,6 +1327,84 @@ 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 align_titlelabels(self, axs=None): + """ + Align the xlabels of subplots in the same subplot column if label + alignment is being done automatically (i.e. the label position is + not manually set). + + Alignment persists for draw events after this is called. + + If a label is on the bottom, it is aligned with labels on Axes that + also have their label on the bottom and that have the same + bottom-most subplot row. If the label is on the top, + it is aligned with labels on Axes with the same top-most row. + + Parameters + ---------- + axs : list of `~matplotlib.axes.Axes` + Optional list of (or `~numpy.ndarray`) `~matplotlib.axes.Axes` + to align the xlabels. + Default is to align all Axes on the figure. + + See Also + -------- + matplotlib.figure.Figure.align_ylabels + matplotlib.figure.Figure.align_labels + + Notes + ----- + This assumes that ``axs`` are from the same `.GridSpec`, so that + their `.SubplotSpec` positions correspond to figure positions. + + Examples + -------- + Example with rotated xtick labels:: + + fig, axs = plt.subplots(1, 2) + for tick in axs[0].get_xticklabels(): + tick.set_rotation(55) + axs[0].set_xlabel('XLabel 0') + axs[1].set_xlabel('XLabel 1') + fig.align_xlabels() + """ + if axs is None: + axs = self.axes + axs = np.ravel(axs) + axs = [ax for ax in axs if hasattr(ax, 'get_subplotspec')] + locs = ['left', 'center', 'right'] + for ax in axs: + for loc in locs: + if ax.get_title(loc=loc): + _log.debug(' Working on: %s', ax.get_title(loc=loc)) + rowspan = ax.get_subplotspec().rowspan + for axc in axs: + for loc in locs: + rowspanc = axc.get_subplotspec().rowspan + if rowspan.start == rowspanc.start or \ + rowspan.stop == rowspanc.stop: + self._align_label_groups['title'].join(ax, axc) + + if axs is None: + axs = self.axes + axs = [ax for ax in np.ravel(axs) if ax.get_subplotspec() is not None] + for ax in axs: + _log.debug(' Working on: %s', ax.get_xlabel()) + rowspan = ax.get_subplotspec().rowspan + pos = ax.xaxis.get_label_position() # top or bottom + # Search through other axes for label positions that are same as + # this one and that share the appropriate row number. + # Add to a grouper associated with each axes of siblings. + # This list is inspected in `axis.draw` by + # `axis._update_label_position`. + for axc in axs: + if axc.xaxis.get_label_position() == pos: + rowspanc = axc.get_subplotspec().rowspan + if (pos == 'top' and rowspan.start == rowspanc.start or + pos == 'bottom' and rowspan.stop == rowspanc.stop): + # grouper for groups of xlabels to align + self._align_label_groups['title'].join(ax, axc) + def align_xlabels(self, axs=None): """ Align the xlabels of subplots in the same subplot column if label From e84960d63cd9489547bb71579faf22c3784c59b6 Mon Sep 17 00:00:00 2001 From: David Sebode Date: Thu, 30 Mar 2023 11:01:38 +0200 Subject: [PATCH 02/12] Fixed bbox issue not being updated when title position is changed. --- lib/matplotlib/figure.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 40bf5a74e97c..d25ca908990f 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1405,6 +1405,39 @@ def align_titlelabels(self, axs=None): # grouper for groups of xlabels to align self._align_label_groups['title'].join(ax, axc) + + #################################################################### + # + # + # MOST BRILLIANT FIX IN THE WORLD INCOMMING + # + # + #################################################################### + # Fixes the issue that the bbox is too small to fit the alligned title + # axs[0] because axs contains all plots in order (because of np.raval(axs)) + # and there must be at least one plot at axs 0 + axs[0].get_tightbbox() + + # if axs is None: + # axs = self.axes + # axs = [ax for ax in np.ravel(axs) if ax.get_subplotspec() is not None] + # for ax in axs: + # _log.debug(' Working on: %s', ax.get_xlabel()) + # rowspan = ax.get_subplotspec().rowspan + # pos = ax.xaxis.get_label_position() # top or bottom + # # Search through other axes for label positions that are same as + # # this one and that share the appropriate row number. + # # Add to a grouper associated with each axes of siblings. + # # This list is inspected in `axis.draw` by + # # `axis._update_label_position`. + # for axc in axs: + # if axc.xaxis.get_label_position() == pos: + # rowspanc = axc.get_subplotspec().rowspan + # if (pos == 'top' and rowspan.start == rowspanc.start or + # pos == 'bottom' and rowspan.stop == rowspanc.stop): + # # grouper for groups of xlabels to align + # self._align_label_groups['title'].join(ax, axc) + def align_xlabels(self, axs=None): """ Align the xlabels of subplots in the same subplot column if label @@ -1549,6 +1582,7 @@ def align_labels(self, axs=None): """ self.align_xlabels(axs=axs) self.align_ylabels(axs=axs) + self.align_titlelabels(axs=axs) def add_gridspec(self, nrows=1, ncols=1, **kwargs): """ From d6d5d7f7bfdff797f9e49009822b65f875af8752 Mon Sep 17 00:00:00 2001 From: David Sebode Date: Thu, 30 Mar 2023 11:14:16 +0200 Subject: [PATCH 03/12] Renamed align_titles to avoid confusion with the axis labels. Also removed align_titlelabels from align_labels since align_labels should only align the axis labels, not the title itself. --- lib/matplotlib/figure.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index d25ca908990f..23c1fb1a0f8e 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1327,7 +1327,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 align_titlelabels(self, axs=None): + def align_title(self, axs=None): """ Align the xlabels of subplots in the same subplot column if label alignment is being done automatically (i.e. the label position is @@ -1406,17 +1406,7 @@ def align_titlelabels(self, axs=None): self._align_label_groups['title'].join(ax, axc) - #################################################################### - # - # - # MOST BRILLIANT FIX IN THE WORLD INCOMMING - # - # - #################################################################### - # Fixes the issue that the bbox is too small to fit the alligned title - # axs[0] because axs contains all plots in order (because of np.raval(axs)) - # and there must be at least one plot at axs 0 - axs[0].get_tightbbox() + axs[0].get_tightbbox() # Fixes the issue that the bbox is too small to fit the alligned title when saving the figure # if axs is None: # axs = self.axes @@ -1582,7 +1572,6 @@ def align_labels(self, axs=None): """ self.align_xlabels(axs=axs) self.align_ylabels(axs=axs) - self.align_titlelabels(axs=axs) def add_gridspec(self, nrows=1, ncols=1, **kwargs): """ From 065d992eb36ad02eee7e8b819063c29c954e2300 Mon Sep 17 00:00:00 2001 From: Alex van Diepen Date: Thu, 30 Mar 2023 11:30:40 +0200 Subject: [PATCH 04/12] Added tests from original pull request to test our solution --- lib/matplotlib/figure.py | 2 +- lib/matplotlib/tests/test_figure.py | 30 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 23c1fb1a0f8e..ece3a35c57c2 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1327,7 +1327,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 align_title(self, axs=None): + def align_titles(self, axs=None): """ Align the xlabels of subplots in the same subplot column if label alignment is being done automatically (i.e. the label position is diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index d8b06003cd00..1a561fa4fb83 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -101,6 +101,36 @@ def test_align_labels_stray_axes(): np.testing.assert_allclose(xn[:2], xn[2:]) np.testing.assert_allclose(yn[::2], yn[1::2]) +## TODO add image comparison +@image_comparison(['figure_align_titles'], extensions=['png', 'svg'], + tol=0 if platform.machine() == 'x86_64' else 0.01) +def test_align_titles(): + fig, axs = plt.subplots(2, 2, + subplot_kw={"xlabel": "x", "ylabel": "", + "title": "Title"}) + axs[0][0].imshow(plt.np.zeros((5, 3))) + axs[0][1].imshow(plt.np.zeros((3, 5))) + axs[1][0].imshow(plt.np.zeros((2, 1))) + axs[1][1].imshow(plt.np.zeros((1, 2))) + + axs[0][1].set_title('Title2', loc="left") + + fig.align_titles() + +## TODO add image comparison +@image_comparison(['figure_align_titles_param'], extensions=['png', 'svg'], + tol=0 if platform.machine() == 'x86_64' else 0.01) +def test_align_titles_param(): + fig, axs = plt.subplots(2, 2, + subplot_kw={"xlabel": "x", "ylabel": "", + "title": "t"}) + axs[0][0].imshow(plt.np.zeros((3, 5))) + axs[0][1].imshow(plt.np.zeros((5, 3))) + axs[1][0].imshow(plt.np.zeros((2, 1))) + axs[1][1].imshow(plt.np.zeros((1, 2))) + + fig.align_titles([axs[0][0], axs[0][1]]) + def test_figure_label(): # pyplot figure creation, selection, and closing with label/number/instance From 7f5220ad7680cef766771067a4495e740fb307ec Mon Sep 17 00:00:00 2001 From: Alex van Diepen Date: Thu, 30 Mar 2023 12:52:42 +0200 Subject: [PATCH 05/12] Changed test to try different way of accessing savefig function as currently it is not showing consistent behaviour --- lib/matplotlib/figure.py | 20 -------------------- lib/matplotlib/tests/test_figure.py | 8 ++++---- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index ece3a35c57c2..7e4cbd3a116b 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1408,26 +1408,6 @@ def align_titles(self, axs=None): axs[0].get_tightbbox() # Fixes the issue that the bbox is too small to fit the alligned title when saving the figure - # if axs is None: - # axs = self.axes - # axs = [ax for ax in np.ravel(axs) if ax.get_subplotspec() is not None] - # for ax in axs: - # _log.debug(' Working on: %s', ax.get_xlabel()) - # rowspan = ax.get_subplotspec().rowspan - # pos = ax.xaxis.get_label_position() # top or bottom - # # Search through other axes for label positions that are same as - # # this one and that share the appropriate row number. - # # Add to a grouper associated with each axes of siblings. - # # This list is inspected in `axis.draw` by - # # `axis._update_label_position`. - # for axc in axs: - # if axc.xaxis.get_label_position() == pos: - # rowspanc = axc.get_subplotspec().rowspan - # if (pos == 'top' and rowspan.start == rowspanc.start or - # pos == 'bottom' and rowspan.stop == rowspanc.stop): - # # grouper for groups of xlabels to align - # self._align_label_groups['title'].join(ax, axc) - def align_xlabels(self, axs=None): """ Align the xlabels of subplots in the same subplot column if label diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index 1a561fa4fb83..102bdf4cc574 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -11,6 +11,7 @@ import numpy as np import pytest from PIL import Image +from matplotlib.testing.compare import compare_images import matplotlib as mpl from matplotlib import gridspec @@ -102,8 +103,6 @@ def test_align_labels_stray_axes(): np.testing.assert_allclose(yn[::2], yn[1::2]) ## TODO add image comparison -@image_comparison(['figure_align_titles'], extensions=['png', 'svg'], - tol=0 if platform.machine() == 'x86_64' else 0.01) def test_align_titles(): fig, axs = plt.subplots(2, 2, subplot_kw={"xlabel": "x", "ylabel": "", @@ -114,12 +113,13 @@ def test_align_titles(): axs[1][1].imshow(plt.np.zeros((1, 2))) axs[0][1].set_title('Title2', loc="left") - fig.align_titles() + fig.savefig("./result_images/test_figure/figure_align_titles") + compare_images("./lib/matplotlib/tests/baseline_images/figure_align_titles.png", "./result_images/test_figure/figure_align_titles.png", 0) ## TODO add image comparison @image_comparison(['figure_align_titles_param'], extensions=['png', 'svg'], - tol=0 if platform.machine() == 'x86_64' else 0.01) + tol=0 if platform.machine() == 'x86_64' else 0.01) def test_align_titles_param(): fig, axs = plt.subplots(2, 2, subplot_kw={"xlabel": "x", "ylabel": "", From 838ace38098017516787dbd8062733551153f8cd Mon Sep 17 00:00:00 2001 From: Alex van Diepen Date: Fri, 31 Mar 2023 13:30:11 +0200 Subject: [PATCH 06/12] Updated code comments --- lib/matplotlib/figure.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 7e4cbd3a116b..84dbeb105c46 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1329,27 +1329,26 @@ def subplots_adjust(self, left=None, bottom=None, right=None, top=None, def align_titles(self, axs=None): """ - Align the xlabels of subplots in the same subplot column if label - alignment is being done automatically (i.e. the label position is + Align the titles of subplots in the same subplot column if title + alignment is being done automatically (i.e. the title position is not manually set). Alignment persists for draw events after this is called. - If a label is on the bottom, it is aligned with labels on Axes that - also have their label on the bottom and that have the same - bottom-most subplot row. If the label is on the top, - it is aligned with labels on Axes with the same top-most row. + If the title is on the top, + it is aligned with titles on Axes with the same top-most row. Parameters ---------- axs : list of `~matplotlib.axes.Axes` Optional list of (or `~numpy.ndarray`) `~matplotlib.axes.Axes` - to align the xlabels. - Default is to align all Axes on the figure. + to align the titles. + Default is to align all titles on the figure. See Also -------- matplotlib.figure.Figure.align_ylabels + matplotlib.figure.Figure.align_xlabels matplotlib.figure.Figure.align_labels Notes @@ -1361,12 +1360,16 @@ def align_titles(self, axs=None): -------- Example with rotated xtick labels:: - fig, axs = plt.subplots(1, 2) - for tick in axs[0].get_xticklabels(): - tick.set_rotation(55) - axs[0].set_xlabel('XLabel 0') - axs[1].set_xlabel('XLabel 1') - fig.align_xlabels() + fig, axs = plt.subplots(2, 2, + subplot_kw={"xlabel": "x", "ylabel": "", + "title": "Title"}) + axs[0][0].imshow(plt.np.zeros((5, 3))) + axs[0][1].imshow(plt.np.zeros((3, 5))) + axs[1][0].imshow(plt.np.zeros((2, 1))) + axs[1][1].imshow(plt.np.zeros((1, 2))) + + axs[0][1].set_title('Title2', loc="left") + fig.align_titles() """ if axs is None: axs = self.axes From 9decc204e9b271a79e8b703c8d3a675662504438 Mon Sep 17 00:00:00 2001 From: David Sebode Date: Fri, 31 Mar 2023 14:03:28 +0200 Subject: [PATCH 07/12] Refactoring of align_titles function Did some code cleanup in align_titles and fixed small typos in docstring. --- lib/matplotlib/figure.py | 44 ++++++++++------------------------------ 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index 84dbeb105c46..b0a2feee2f82 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -184,7 +184,7 @@ def __init__(self, **kwargs): self._supylabel = None # groupers to keep track of x, y and title labels we want to align. - # see self.align_xlabels, self.align_ylabels, self.align_titlelabels and + # see self.align_xlabels, self.align_ylabels, self.align_titles and # axis._get_tick_boxes_siblings self._align_label_groups = {"x": cbook.Grouper(), "y": cbook.Grouper(), "title": cbook.Grouper()} @@ -1358,7 +1358,7 @@ def align_titles(self, axs=None): Examples -------- - Example with rotated xtick labels:: + Example with aligned titles on multiple rows:: fig, axs = plt.subplots(2, 2, subplot_kw={"xlabel": "x", "ylabel": "", @@ -1373,43 +1373,21 @@ def align_titles(self, axs=None): """ if axs is None: axs = self.axes - axs = np.ravel(axs) - axs = [ax for ax in axs if hasattr(ax, 'get_subplotspec')] + axs = [ax for ax in np.ravel(axs) if ax.get_subplotspec() is not None] locs = ['left', 'center', 'right'] for ax in axs: for loc in locs: if ax.get_title(loc=loc): - _log.debug(' Working on: %s', ax.get_title(loc=loc)) rowspan = ax.get_subplotspec().rowspan for axc in axs: - for loc in locs: - rowspanc = axc.get_subplotspec().rowspan - if rowspan.start == rowspanc.start or \ - rowspan.stop == rowspanc.stop: - self._align_label_groups['title'].join(ax, axc) - - if axs is None: - axs = self.axes - axs = [ax for ax in np.ravel(axs) if ax.get_subplotspec() is not None] - for ax in axs: - _log.debug(' Working on: %s', ax.get_xlabel()) - rowspan = ax.get_subplotspec().rowspan - pos = ax.xaxis.get_label_position() # top or bottom - # Search through other axes for label positions that are same as - # this one and that share the appropriate row number. - # Add to a grouper associated with each axes of siblings. - # This list is inspected in `axis.draw` by - # `axis._update_label_position`. - for axc in axs: - if axc.xaxis.get_label_position() == pos: - rowspanc = axc.get_subplotspec().rowspan - if (pos == 'top' and rowspan.start == rowspanc.start or - pos == 'bottom' and rowspan.stop == rowspanc.stop): - # grouper for groups of xlabels to align - self._align_label_groups['title'].join(ax, axc) - - - axs[0].get_tightbbox() # Fixes the issue that the bbox is too small to fit the alligned title when saving the figure + rowspanc = axc.get_subplotspec().rowspan + if rowspan.start == rowspanc.start or \ + rowspan.stop == rowspanc.stop: + self._align_label_groups['title'].join(ax, axc) + + # Fixes the issue that the bbox is too small to fit the aligned + # title when saving the figure + axs[0].get_tightbbox() def align_xlabels(self, axs=None): """ From 52164fa86337048e08bc0337f1121a1285d6b30c Mon Sep 17 00:00:00 2001 From: Alex van Diepen Date: Fri, 31 Mar 2023 15:00:49 +0200 Subject: [PATCH 08/12] Fixed flake8 issues --- lib/matplotlib/figure.py | 3 ++- lib/matplotlib/tests/test_figure.py | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index b0a2feee2f82..4ec6003c4b71 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -186,7 +186,8 @@ def __init__(self, **kwargs): # groupers to keep track of x, y and title labels we want to align. # see self.align_xlabels, self.align_ylabels, self.align_titles and # axis._get_tick_boxes_siblings - self._align_label_groups = {"x": cbook.Grouper(), "y": cbook.Grouper(), "title": cbook.Grouper()} + self._align_label_groups = {"x": cbook.Grouper(), "y": cbook.Grouper() + , "title": cbook.Grouper()} self.figure = self self._localaxes = [] # track all axes diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index 102bdf4cc574..25aeb84c4248 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -102,6 +102,7 @@ def test_align_labels_stray_axes(): np.testing.assert_allclose(xn[:2], xn[2:]) np.testing.assert_allclose(yn[::2], yn[1::2]) + ## TODO add image comparison def test_align_titles(): fig, axs = plt.subplots(2, 2, @@ -115,7 +116,9 @@ def test_align_titles(): axs[0][1].set_title('Title2', loc="left") fig.align_titles() fig.savefig("./result_images/test_figure/figure_align_titles") - compare_images("./lib/matplotlib/tests/baseline_images/figure_align_titles.png", "./result_images/test_figure/figure_align_titles.png", 0) + compare_images("./lib/matplotlib/tests/baseline_images/figure_align_titles.png", + "./result_images/test_figure/figure_align_titles.png", 0) + ## TODO add image comparison @image_comparison(['figure_align_titles_param'], extensions=['png', 'svg'], From b44fb004a5da5c0190bd2b74c2d7bf0bbb518e0c Mon Sep 17 00:00:00 2001 From: Alex van Diepen Date: Fri, 31 Mar 2023 15:18:08 +0200 Subject: [PATCH 09/12] Fixed flake8 issues --- 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 4ec6003c4b71..0038c45614c3 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -186,8 +186,8 @@ def __init__(self, **kwargs): # groupers to keep track of x, y and title labels we want to align. # see self.align_xlabels, self.align_ylabels, self.align_titles and # axis._get_tick_boxes_siblings - self._align_label_groups = {"x": cbook.Grouper(), "y": cbook.Grouper() - , "title": cbook.Grouper()} + self._align_label_groups = {"x": cbook.Grouper(), "y": cbook.Grouper(), + "title": cbook.Grouper()} self.figure = self self._localaxes = [] # track all axes From 3741239e17aae4e8eb2b41e98b6d0e38564a50fe Mon Sep 17 00:00:00 2001 From: David Sebode Date: Fri, 31 Mar 2023 15:18:17 +0200 Subject: [PATCH 10/12] Fixed flake8 formating issues --- lib/matplotlib/figure.py | 3 ++- lib/matplotlib/tests/test_figure.py | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/figure.py b/lib/matplotlib/figure.py index b0a2feee2f82..0038c45614c3 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -186,7 +186,8 @@ def __init__(self, **kwargs): # groupers to keep track of x, y and title labels we want to align. # see self.align_xlabels, self.align_ylabels, self.align_titles and # axis._get_tick_boxes_siblings - self._align_label_groups = {"x": cbook.Grouper(), "y": cbook.Grouper(), "title": cbook.Grouper()} + self._align_label_groups = {"x": cbook.Grouper(), "y": cbook.Grouper(), + "title": cbook.Grouper()} self.figure = self self._localaxes = [] # track all axes diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index 102bdf4cc574..25aeb84c4248 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -102,6 +102,7 @@ def test_align_labels_stray_axes(): np.testing.assert_allclose(xn[:2], xn[2:]) np.testing.assert_allclose(yn[::2], yn[1::2]) + ## TODO add image comparison def test_align_titles(): fig, axs = plt.subplots(2, 2, @@ -115,7 +116,9 @@ def test_align_titles(): axs[0][1].set_title('Title2', loc="left") fig.align_titles() fig.savefig("./result_images/test_figure/figure_align_titles") - compare_images("./lib/matplotlib/tests/baseline_images/figure_align_titles.png", "./result_images/test_figure/figure_align_titles.png", 0) + compare_images("./lib/matplotlib/tests/baseline_images/figure_align_titles.png", + "./result_images/test_figure/figure_align_titles.png", 0) + ## TODO add image comparison @image_comparison(['figure_align_titles_param'], extensions=['png', 'svg'], From 4eb53e6fa9da587eab5bab0c4508148a0cccee2e Mon Sep 17 00:00:00 2001 From: David Sebode Date: Mon, 3 Apr 2023 19:00:27 +0200 Subject: [PATCH 11/12] Changed fix for savefig self.canvas.draw_idle() produces more reliable behaviour when generating the plots. Now the titles are alligned every time. --- 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 0038c45614c3..6c9d5cb89a67 100644 --- a/lib/matplotlib/figure.py +++ b/lib/matplotlib/figure.py @@ -1388,7 +1388,7 @@ def align_titles(self, axs=None): # Fixes the issue that the bbox is too small to fit the aligned # title when saving the figure - axs[0].get_tightbbox() + self.canvas.draw_idle() def align_xlabels(self, axs=None): """ From 1fe094aa39d65eb3cdd01e0c61128ab3debe82c3 Mon Sep 17 00:00:00 2001 From: Alex van Diepen Date: Thu, 6 Apr 2023 10:57:02 +0200 Subject: [PATCH 12/12] Changed tests to use new styling standard. Titles now align as expected, however using constrained layout gives some scaling issues now. --- lib/matplotlib/tests/test_figure.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index 25aeb84c4248..0781cc316500 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -104,10 +104,12 @@ def test_align_labels_stray_axes(): ## TODO add image comparison +@image_comparison(['figure_align_titles'], extensions=['png', 'svg'], + tol=0 if platform.machine() == 'x86_64' else 0.01, style='mpl20') def test_align_titles(): fig, axs = plt.subplots(2, 2, subplot_kw={"xlabel": "x", "ylabel": "", - "title": "Title"}) + "title": "Title"}, layout="constrained") axs[0][0].imshow(plt.np.zeros((5, 3))) axs[0][1].imshow(plt.np.zeros((3, 5))) axs[1][0].imshow(plt.np.zeros((2, 1))) @@ -115,18 +117,15 @@ def test_align_titles(): axs[0][1].set_title('Title2', loc="left") fig.align_titles() - fig.savefig("./result_images/test_figure/figure_align_titles") - compare_images("./lib/matplotlib/tests/baseline_images/figure_align_titles.png", - "./result_images/test_figure/figure_align_titles.png", 0) ## TODO add image comparison @image_comparison(['figure_align_titles_param'], extensions=['png', 'svg'], - tol=0 if platform.machine() == 'x86_64' else 0.01) + tol=0 if platform.machine() == 'x86_64' else 0.01, style='mpl20') def test_align_titles_param(): fig, axs = plt.subplots(2, 2, subplot_kw={"xlabel": "x", "ylabel": "", - "title": "t"}) + "title": "t"}, layout="constrained") axs[0][0].imshow(plt.np.zeros((3, 5))) axs[0][1].imshow(plt.np.zeros((5, 3))) axs[1][0].imshow(plt.np.zeros((2, 1)))