Skip to content

Conversation

@anntzer
Copy link
Contributor

@anntzer anntzer commented Jan 27, 2026

To figure out which axes need to be restored, mappable.axes is less reliable than _colorbar_info["parents"].

Why the tests now need a greater (though still tiny) tolerance to make the "orphan mappable" case pass is a mystery.

Closes #22257.

PR summary

PR checklist

np.testing.assert_allclose(pre_position.get_points(),
post_position.get_points())
np.testing.assert_allclose(
pre_position.get_points(), post_position.get_points(), atol=0.0002)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do both orphan_mappable values need the tolerance or is this specific to the new orphan_mappable = True case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Actually this is more complicated than expected, because constrained_layout uses make_axes, not make_axes_gridspec, i.e. it needs another position restoring strategy. I'll need to check whether all the relevant info is in colorbar_info...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you remove the colorbar under constrained layout it should just readjust on its own? My memory is hazy, but I'm pretty sure there is a "column" (or row) reserved for the colorbar, and if there is no colorbar it just collapses to zero width (height)?

Comment on lines 1030 to 1032
for a in parents:
if self.ax in a._colorbars:
a._colorbars.remove(self.ax)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While at it, let's make the naming more clear

Suggested change
for a in parents:
if self.ax in a._colorbars:
a._colorbars.remove(self.ax)
for ax in parents:
if self.ax in ax._colorbars:
ax._colorbars.remove(self.ax)

Also, semi-OT and probably rather suitable for a separate PR:

  • I think parents is somewhat a misnomer. Unlike e.g. inset_axes() the colorbar Axes is not added as a child to the Axes it steals from, i.e. self.ax in self._axes_info["parents"][0].get_children() is False.
  • getattr(self.ax, "_colorbar_info", {}).get("parents", []) feels to dynamic. Should we (1) turn the dict into a dataclass (fixed set of defined fields)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Renamed to ax.
  • The second get() was only to handle the case where _colorbar_info doesn't exist at all (if self.ax was not created by make_axes -- typically a manually created axes passed as colorbar(cax=...)). I made this a bit simpler.
  • I'll punt renaming "parents" for another time...

and parents[0].get_subplotspec()
and (self.ax.get_subplotspec().get_gridspec()
is parents[0].get_subplotspec().get_gridspec())):
parents[0].set_subplotspec(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we only reset parents[0]. What happens for the case colorbar(ax=[ax1, ax2])?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If borrowing from multiple colorbars we never actually rely on use_gridspec=True (see Figure.colorbar) so self.ax.get_subplotspec() will already be false above; in any case I also check for len(parents) == 1 just above just to be safe.

To figure out which axes need to be restored, `mappable.axes` is less
reliable than `_colorbar_info["parents"]`.

Why the tests now need a greater (though still tiny) tolerance to make
the "orphan mappable" case pass is a mystery.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: colorbar.remove() does not always work

3 participants