Search code examples
pythonmatplotlibcolorbar

How to "cut" the unwanted part of a colorbar


Say you create an image with imshow like this:

plt.set_cmap('viridis')
im=plt.imshow(mydata, interpolation='nearest',origin='lower')
plt.title('mymap')
cbar=plt.colorbar()
a=round(mydata.max(),0)
cbar.set_ticks([17,23,a])
cbar.set_ticklabels([17,23,a])

Say you have a continuous-like dataset where most values are 0, but then there's a jump leading to the range of highest values.

How do you "cut" the colorbar to make sure it starts from mydata.min()=17, ends at mydata.max()=27, without changing the colors in the image?


I don't want this:

enter image description here


Solution

  • There is no standard solution for limiting the color range in a colorbar, because the shown colors are usually directly linked to the colors in the image.

    The solution would therefore be to create a colorbar, which is independent on the image, filled with a different colormap. This additional colormap can be taken from the original one by cutting out the respective portion one needs.

    import matplotlib.pyplot as plt
    import matplotlib
    import matplotlib.colors
    import numpy as np
    
    # some data between 0 and 27
    image = np.random.rand(30,60)*27
    image[:,30:] = np.sort(image[:,30:].flatten()).reshape(30,30)
    
    
    plt.figure(figsize=(8,3))
    cmap = plt.get_cmap('jet')
    im=plt.imshow(image, interpolation='nearest',origin='lower', cmap = cmap)
    plt.title('mymap')
    
    
    a=round(image.max(),0)
    
    vmin=17  #minimum value to show on colobar
    vmax = a #maximum value to show on colobar
    norm = matplotlib.colors.Normalize(vmin=vmin, vmax =vmax)
    #generate colors from original colormap in the range equivalent to [vmin, vamx] 
    colors = cmap(np.linspace(1.-(vmax-vmin)/float(vmax), 1, cmap.N))
    # Create a new colormap from those colors
    color_map = matplotlib.colors.LinearSegmentedColormap.from_list('cut_jet', colors)
    
    # create some axes to put the colorbar to
    cax, _  = matplotlib.colorbar.make_axes(plt.gca())
    cbar = matplotlib.colorbar.ColorbarBase(cax, cmap=color_map, norm=norm,)
    
    cbar.set_ticks([17,23,a])
    cbar.set_ticklabels([17,23,a])
    
    plt.show()
    

    enter image description here