Skip to content

[Bug]: inset colorbar colours and frame misaligned #29383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
rcomer opened this issue Dec 28, 2024 · 5 comments
Open

[Bug]: inset colorbar colours and frame misaligned #29383

rcomer opened this issue Dec 28, 2024 · 5 comments

Comments

@rcomer
Copy link
Member

rcomer commented Dec 28, 2024

Bug summary

Following #29340, when a colorbar is added in an inset axes there is still a small mismatch between the frame and the colours of the colorbar, as shown in the test image added at #29340. That test uses the toolkits inset_axes but the problem also appears when using Axes.inset_axes.

Code for reproduction

From #27763 (comment):

import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(1, 1, layout='constrained')

x = np.random.randint(100, size=(30, 200))
c = axes.imshow(x, origin='lower', cmap='Reds', aspect=1)
axins1 = axes.inset_axes([0.05, 0.8, 0.2, 0.09])

fig.colorbar(c, cax=axins1, orientation="horizontal")

fig.savefig('test_single.pdf', bbox_inches='tight')

Actual outcome

image

Expected outcome

Colorbar frame should be lined up with its colours.

Additional information

To reproduce the bug we need

  • Rasterized artist in inset_axes
  • Saving with bbox_inches='tight'
  • Saving as pdf, so perhaps linked to the mixed-mode renderer calling adjust_bbox multiple times via process_figure_for_rasterizing.

Increasing the figure dpi to 300 makes the problem disappear. Also, when I originally wrote the test at #29340 I forgot to set the style. The problem did not show up with classic mode.

I have reproduced with v3.2, so probably this never worked.

Operating system

Ubuntu

Matplotlib Version

main

Matplotlib Backend

QtAgg

Python version

3.12.5

Jupyter version

n/a

Installation

git checkout

@rcomer
Copy link
Member Author

rcomer commented Jan 5, 2025

Note this is not specific to Colorbar - we can also reproduce with

r = mpatch.Rectangle((0, 0), 1, 1)
r.set_rasterized(True)
axins1.add_patch(r)

image

@rcomer
Copy link
Member Author

rcomer commented Jan 5, 2025

We can also reproduce without bbox_inches='tight', by picking a figure size that does not translate to a round number of pixels

figsize=(6.4, 4.807), dpi=100

Note that the Agg renderer rounds down with int

self._renderer = _RendererAgg(int(width), int(height), dpi)

@timhoffm
Copy link
Member

timhoffm commented Jan 5, 2025

Is this a rounding vs. truncating issue? It may be that we are not consistent with that.

@rcomer
Copy link
Member Author

rcomer commented Jan 5, 2025

The problem goes away with the following, which makes the vector renderer use the same size in inches as Agg used.

diff --git a/lib/matplotlib/backends/backend_mixed.py b/lib/matplotlib/backends/backend_mixed.py
index ea8f50a39a..234954bbfc 100644
--- a/lib/matplotlib/backends/backend_mixed.py
+++ b/lib/matplotlib/backends/backend_mixed.py
@@ -76,8 +76,14 @@ class MixedModeRenderer:
         # change the dpi of the figure temporarily.
         self.figure.dpi = self.dpi
 
+        width_pixels = int(self._width * self.dpi)
+        height_pixels = int(self._height * self.dpi)
+
+        self._width = width_pixels / self.dpi
+        self._height = height_pixels / self.dpi
+
         self._raster_renderer = self._raster_renderer_class(
-            self._width*self.dpi, self._height*self.dpi, self.dpi)
+            width_pixels, height_pixels, self.dpi)
         self._renderer = self._raster_renderer
 
         if self._bbox_inches_restore:  # when tight bbox is used

This causes three image test failures, but they all look like improvements:

test_bbox_inches_tight_raster (pdf and svg) goes from

bbox_inches_tight_raster-expected_svg

to

bbox_inches_tight_raster_svg

Easier to see when flicking between the two in a viewer, but the blue line now looks better aligned in the corners.

test_bbox_inches_inset_rasterized goes from
bbox_inches_inset_rasterized-expected_pdf
to
bbox_inches_inset_rasterized_pdf

I am too far out of my depth to say whether this is actually the correct fix!

@rcomer
Copy link
Member Author

rcomer commented Jan 29, 2025

I just realised this is probably the same as #6827 which has an orphaned PR.

Edit: my patch does not fix #6827.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants