FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

[Bug]: colorbar doesn't register inset_axis as cax · Issue #27763 · matplotlib/matplotlib · GitHub

Repository navigation

[Bug]: colorbar doesn't register inset_axis as cax  #27763

Closed

Description

Bug summary

When constructing inset axes using the tutorial on this page the gradient of the colorbar does not appear in the constructed inset axis but somewhere else on the figure (location seems to depend on figure size) once saved to a PDF with multiple other figures if bbox_inches='tight'. Similar to #27143 and #25176.

Code for reproduction

from mpl_toolkits.axes_grid1.inset_locator import inset_axes
import matplotlib.pylab as plt
from matplotlib.backends.backend_pdf import PdfPages

#make the first figure
fig, axes = plt.subplots(1, 1, facecolor = 'white', figsize = (20, 5), constrained_layout = True)

x = random.randint(100, size=(100, 2048))
c = axes.imshow(x, origin = 'lower', cmap = 'Reds', vmin = 0, vmax = 100, aspect = "auto")
axins1 = inset_axes(axes,
                    width="10%",
                    height="30%",
                    loc="upper left",
                    bbox_to_anchor = (0.045, 0., 1, 1),
                    bbox_transform = axes.transAxes
                    )
axins1.xaxis.set_ticks_position("bottom")
fig.colorbar(c, cax=axins1, orientation="horizontal")
axes.set_yticklabels([])

fig.suptitle("Title")
plt.figtext(-0.02, 0.5, 'Random', c = 'k', rotation = 90, ma = 'center', fontsize = medium)

#make figure 2
fig2, axes = plt.subplots(1, 1, facecolor = 'white', figsize = (20, 5), constrained_layout = True)

x = random.randint(100, size=(100, 2048))
c = axes.imshow(x, origin = 'lower', cmap = 'Reds', vmin = 0, vmax = 100, aspect = "auto")
axins1 = inset_axes(axes,
                    width="10%",
                    height="30%",
                    loc="upper left",
                    bbox_to_anchor = (0.045, 0., 1, 1),
                    bbox_transform = axes.transAxes
                    )
axins1.xaxis.set_ticks_position("bottom")
fig2.colorbar(c, cax=axins1, orientation="horizontal")
axes.set_yticklabels([])

fig2.suptitle("Title")
plt.figtext(-0.02, 0.5, 'Random', c = 'k', rotation = 90, ma = 'center', fontsize = medium)

#save figs to PDF
figs = [fig, fig2]
with PdfPages('test.pdf') as pdf:
    for fig in figs:
        pdf.savefig(fig, bbox_inches='tight')

Actual outcome

The gradient for the colorbar appears outside of the inset axes on each of the plots
test_small.pdf

Expected outcome

The result for this particular example when bbox_inches='tight' is not called in savefig(). Note: when running in jupyter lab this is always the outcome--only when saving the figure does the gradient jump out of the inset axis.
test_loose.pdf

Additional information

I tried the same suggestion as in #27143 and used axins1 = axes.inset_axes([0.05, 0.7, 0.1, 0.2], transform = axes.transAxes) in my own code which seemed to fix this. Unsure why the example constructor for inset_axes here doesn't work in this case.

Operating system

Mac OS 13.6.3 (Ventura) Intel

Matplotlib Version

3.8.0

Matplotlib Backend

Installed osx event loop hook. MacOSX

Python version

Python 3.9.18

Jupyter version

Jupyter Lab 3.6.3

Installation

conda

Activity

  1. jklymak commented on Feb 8, 2024

    Member
  2. rcomer commented on Feb 9, 2024

    Member

    This can be reproduced more simply with

    from mpl_toolkits.axes_grid1.inset_locator import inset_axes
    import matplotlib.pyplot as plt
    import numpy as np
    
    fig, axes = plt.subplots(1, 1)
    
    x = np.random.randint(100, size=(10, 200))
    c = axes.imshow(x, origin='lower', cmap='Reds', aspect='auto')
    axins1 = inset_axes(axes,
                        width="10%",
                        height="30%",
                        loc="upper left",
                        bbox_to_anchor = (0.045, 0., 1, 1),
                        bbox_transform = axes.transAxes
                        )
    
    fig.colorbar(c, cax=axins1, orientation="horizontal")
    
    fig.savefig('test_single.png', bbox_inches='tight')
    fig.savefig('test_single.pdf', bbox_inches='tight')

    The png is fine, the pdf shows the problem. Confirmed broken on main.

  3. rcomer commented on Feb 9, 2024

    Member

    I can reproduce this in v3.7.3 but not in v3.7.1. The code won't run at v3.7.2 because of #26287.

  4. rcomer commented on Feb 9, 2024

    Member

    If I branch off v3.7.x and drop the commit from #25499 (which caused #26287), I cannot reproduce.

  5. jklymak commented on Feb 9, 2024

    Member
    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.png', bbox_inches='tight')
    fig.savefig('test_single.pdf', bbox_inches='tight')
    

    Also seems to have a small error in the placement of the colorbar's colors in PDF:

    This doesn't happen if you dont' use bbox_inches='tight', so maybe the same bug, but much more subtle

  6. l4nc3l0t commented on Feb 22, 2024

    similar problem with cartopy and inset. when saving figure in pdf with bbox_inches='tight' the colorbar's colors is moving with matplotlib 3.8.3. Solved by using matplotlib 3.7.1

  7. imcvis commented on Apr 1, 2024

    same problem here, solved downgrading to 3.7.1

  8. rcomer commented on Apr 2, 2024

    Member

    I think this may have something to do with a dpi mismatch. If I remove this line

    # _get_renderer may change the figure dpi (as vector formats
    # force the figure dpi to 72), so we need to set it again here.
    with cbook._setattr_cm(self.figure, dpi=dpi):

    the problem is fixed (though of course other tests fail).

    Edit: it also doesn't fix the more subtle case from #27763 (comment)

  9. rcomer commented on Apr 2, 2024

    Member

    Also specific to rasterization. If we skip this line

    self.solids.set_rasterized(True)

    the colours are positioned where they should be (though they don't look great) both for the main axes_grid1 case and the case from #27763 (comment).

    Do rasterized objects only get drawn on the first draw or something?

  10. andrewkhardy commented on Jun 13, 2024

    I'm wondering if there is an update to this , I'm having the same issue where the color of the bar is getting rasterized and so showing up at bottom left of imshow when I don't want it there

  11. ericasaw commented on Jun 13, 2024

    Author

    The temporary solution I found was to use something like axins1 = axes.inset_axes([0.05, 0.7, 0.1, 0.2], transform = axes.transAxes) to make an inset axis in a specific place and then to put the color bar into that inset axis when plotting.

  12. tacaswell commented on Jun 13, 2024

    Member

    To summarize this issue is when we have a combination of:

    • bbox_inches='tight'
    • rasterized artists in an inset axes

    The way bbox_inches='tight' works is by updating the base transform in a somewhat fancy way. The amount of offset seems to depend on the original figure size which suggests that this is either a caching or a rounding issue.

  13. added this to the v3.11.0 milestone on Dec 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL