Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e5562bb

Browse files
authored
Check if the mappable is in a different Figure than the one fig.color… (#27458)
* Check if the mappable is in a different Figure than the one fig.colorbar is being called on. Ignore this check if the mappable has no host Figure. Warn in case of a mismatch. * Add figure repr in warning message. * Use _api.warn_external instead of _log.warning. Only warn when the mismatch is inferred. * Delete test_colorbar::test_colorbar_wrong_figure. * Warn in all mismatches, inferred or not. * Revert deletion of test_colorbar_wrong_figure, with warning test. * Linting fixes * Catch newly added warning raised in other test cases. * Catch warning in existing test cases. * edge case: subfigure. only warn when top level artist don't match. * flake8 code style check fix * code style fix. * subfigure test cases revert: no warning. * Fix edge case: axes.remove(); passing correct pcolormesh object in galleries. * remove redundant lines * code stylistic fix
1 parent 30ddba9 commit e5562bb

File tree

4 files changed

+53
-4
lines changed

4 files changed

+53
-4
lines changed

galleries/users_explain/axes/colorbar_placement.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
fig, axs = plt.subplots(2, 1, figsize=(4, 5), sharex=True)
5454
X = np.random.randn(20, 20)
5555
axs[0].plot(np.sum(X, axis=0))
56-
axs[1].pcolormesh(X)
56+
pcm = axs[1].pcolormesh(X)
5757
fig.colorbar(pcm, ax=axs[1], shrink=0.6)
5858

5959
# %%
@@ -63,7 +63,7 @@
6363

6464
fig, axs = plt.subplots(2, 1, figsize=(4, 5), sharex=True, layout='constrained')
6565
axs[0].plot(np.sum(X, axis=0))
66-
axs[1].pcolormesh(X)
66+
pcm = axs[1].pcolormesh(X)
6767
fig.colorbar(pcm, ax=axs[1], shrink=0.6)
6868

6969
# %%

lib/matplotlib/figure.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,19 @@ def colorbar(
12421242
fig.sca(current_ax)
12431243
cax.grid(visible=False, which='both', axis='both')
12441244

1245+
if hasattr(mappable, "figure") and mappable.figure is not None:
1246+
# Get top level artists
1247+
mappable_host_fig = mappable.figure
1248+
if isinstance(mappable_host_fig, mpl.figure.SubFigure):
1249+
mappable_host_fig = mappable_host_fig.figure
1250+
# Warn in case of mismatch
1251+
if mappable_host_fig is not self.figure:
1252+
_api.warn_external(
1253+
f'Adding colorbar to a different Figure '
1254+
f'{repr(mappable.figure)} than '
1255+
f'{repr(self.figure)} which '
1256+
f'fig.colorbar is called on.')
1257+
12451258
NON_COLORBAR_KEYS = [ # remove kws that cannot be passed to Colorbar
12461259
'fraction', 'pad', 'shrink', 'aspect', 'anchor', 'panchor']
12471260
cb = cbar.Colorbar(cax, mappable, **{

lib/matplotlib/tests/test_colorbar.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1228,7 +1228,8 @@ def test_colorbar_wrong_figure():
12281228
im = fig_cl.add_subplot().imshow([[0, 1]])
12291229
# Make sure this doesn't try to setup a gridspec-controlled colorbar on fig_cl,
12301230
# which would crash CL.
1231-
fig_tl.colorbar(im)
1231+
with pytest.warns(UserWarning, match="different Figure"):
1232+
fig_tl.colorbar(im)
12321233
fig_tl.draw_without_rendering()
12331234
fig_cl.draw_without_rendering()
12341235

lib/matplotlib/tests/test_figure.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1358,7 +1358,6 @@ def test_subfigure_double():
13581358
ax.set_xlabel('x-label', fontsize=fontsize)
13591359
ax.set_ylabel('y-label', fontsize=fontsize)
13601360
ax.set_title('Title', fontsize=fontsize)
1361-
13621361
subfigsnest[0].colorbar(pc, ax=axsnest0)
13631362

13641363
subfigsnest[1].suptitle('subfigsnest[1]')
@@ -1665,3 +1664,39 @@ def test_not_visible_figure():
16651664
fig.savefig(buf, format='svg')
16661665
buf.seek(0)
16671666
assert '<g ' not in buf.read()
1667+
1668+
1669+
def test_warn_colorbar_mismatch():
1670+
fig1, ax1 = plt.subplots()
1671+
fig2, (ax2_1, ax2_2) = plt.subplots(2)
1672+
im = ax1.imshow([[1, 2], [3, 4]])
1673+
1674+
fig1.colorbar(im) # should not warn
1675+
with pytest.warns(UserWarning, match="different Figure"):
1676+
fig2.colorbar(im)
1677+
# warn mismatch even when the host figure is not inferred
1678+
with pytest.warns(UserWarning, match="different Figure"):
1679+
fig2.colorbar(im, ax=ax1)
1680+
with pytest.warns(UserWarning, match="different Figure"):
1681+
fig2.colorbar(im, ax=ax2_1)
1682+
with pytest.warns(UserWarning, match="different Figure"):
1683+
fig2.colorbar(im, cax=ax2_2)
1684+
1685+
# edge case: only compare top level artist in case of subfigure
1686+
fig3 = plt.figure()
1687+
fig4 = plt.figure()
1688+
subfig3_1 = fig3.subfigures()
1689+
subfig3_2 = fig3.subfigures()
1690+
subfig4_1 = fig4.subfigures()
1691+
ax3_1 = subfig3_1.subplots()
1692+
ax3_2 = subfig3_1.subplots()
1693+
ax4_1 = subfig4_1.subplots()
1694+
im3_1 = ax3_1.imshow([[1, 2], [3, 4]])
1695+
im3_2 = ax3_2.imshow([[1, 2], [3, 4]])
1696+
im4_1 = ax4_1.imshow([[1, 2], [3, 4]])
1697+
1698+
fig3.colorbar(im3_1) # should not warn
1699+
subfig3_1.colorbar(im3_1) # should not warn
1700+
subfig3_1.colorbar(im3_2) # should not warn
1701+
with pytest.warns(UserWarning, match="different Figure"):
1702+
subfig3_1.colorbar(im4_1)

0 commit comments

Comments
 (0)