pythonmatplotlibcolorbar

Matplotlib colorbar with fixed aspect ratio


I have a grid (say 2x2) of subplots with constrained layout and I want to have a colorbar of the total height of the figure right next to it as follows:

fig, axes = plt.subplots(nrows=2,ncols=2,layout='constrained')

for ax in axes.flat:

    stuff = ax.pcolormesh(np.random.randn(20, 20), cmap='viridis')
    
#    ax.set_box_aspect(1/2)

fig1.colorbar(stuff,ax= axes.ravel().tolist())  # add a color legend

plt.show()

This looks fine and exactly how I want it. However, as soon as I uncomment the line where I set the (box) aspect, the colorbar is too high.

I tried different things like inset_axis which is suggested in the tutorial (https://matplotlib.org/stable/users/explain/axes/colorbar_placement.html#manual-placement-of-colorbars) but as I want the colorbar to extend over two axes, this doesn't work.

Any help?


Solution

  • You can use ImageGrid from mpl_toolkits.axes_grid1

    from mpl_toolkits.axes_grid1 import ImageGrid
    

    I used random data:

    # Example data
    Z = np.random.rand(10, 10)
    extent = (-10, 10, -10, 10)
    
    # Define aspect ratio (width-to-height)
    aspect_ratio = .5  # Width is twice the height
    

    Create the figure

    fig = plt.figure(figsize=(10, 8))  
    
    # Create a 2x2 grid of images with a single colorbar on the right
    grid = ImageGrid(
        fig, 111,  # Position in the figure
        nrows_ncols=(2, 2),  
        axes_pad=(0.1, 0.4),  
        label_mode="L",  
        share_all=True,  # Share axes limits
        cbar_location="right",  # Place the colorbar on the right
        cbar_mode="single",  # One colorbar for all plots
        cbar_size="3%",  # Slimmer colorbar
        cbar_pad=0.2,  # Padding between grid and colorbar
    )
    

    Add images to the grid and control the aspect ratio

    for ax in grid:
        im = ax.imshow(Z, extent=extent, cmap="viridis", aspect=1/aspect_ratio)
    

    Add the colorbar

    grid.cbar_axes[0].colorbar(im)
    

    Configure ticks and axes labels

    for cax in grid.cbar_axes:
        cax.tick_params(labelright=True)  # Show ticks on the right
    grid.axes_llc.set(xticks=[-10, 0, 10], yticks=[-10, 0, 10])
    

    enter image description here

    enter image description here