Matplotlib normalize colorbar (Python)
Asked Answered
H

3

6

I'm trying to plot a contourf-plot using matplotlib (and numpy of course). And it works, it plots what it should plot, but unfortunatelly I cannot set the colorbar range. The problem is that I have a plenty of plots and need all of them to have the same colorbar (same min and max, same colors). I copy&past-ed almost every code snippet I found on the internet, but without success. My code so far:

    import numpy as np;
    import matplotlib as mpl;
    import matplotlib.pyplot as plt;
    [...]
    plotFreq, plotCoord = np.meshgrid(plotFreqVect, plotCoordVect);

    figHandler = plt.figure();
    cont_PSD = plt.contourf(plotFreq, plotCoord, plotPxx, 200, linestyle=None);


    normi = mpl.colors.Normalize(vmin=-80, vmax=20);

    colbar_PSD = plt.colorbar(cont_PSD);
    colbar_PSD.set_norm(normi);
    #colbar_PSD.norm = normi;
    #mpl.colors.Normalize(vmin=-80, vmax=20);

    plt.axis([1, 1000, -400, 400]);

As you can see there are three different lines for the colorbar norm, none of them is working. The range is still set automatically... I mean everything else is working, why not the colorbar? I don't even get errors or warnings.

Thanks, itpdg

EDIT 1: Pictures, with plt.clim(-80,20):

enter image description here

Holofernes answered 22/2, 2016 at 15:3 Comment(0)
C
2

Please user the levels parameter, a set of examples:

In [9]:

ndom
z = np.random.random((10,10))

Without levels, colorbar will be auto-scaled

In [11]:
plt.contourf(z)
plt.colorbar()
Out[11]:
<matplotlib.colorbar.Colorbar at 0x120d47390>

enter image description here

In [12]:
plt.contourf(z*2)
plt.colorbar()
Out[12]:
<matplotlib.colorbar.Colorbar at 0x120f6ac10>

enter image description here

Control colorbar with explicit levels

In [13]:
plt.contourf(z*2, levels=np.linspace(0,2,20))
plt.colorbar()
Out[13]:
<matplotlib.colorbar.Colorbar at 0x121b119d0>

enter image description here

In [14]:
plt.contourf(z, levels=np.linspace(0,2,20))
plt.colorbar()
Out[14]:
<matplotlib.colorbar.Colorbar at 0x120dc3510>

enter image description here

Campball answered 22/2, 2016 at 16:51 Comment(2)
Oh okay thanks! But then there's another problem. I need vmin=-80, vmax=20, but have values smaller than -80. Matlab just plots them with the "smallest color", python seems to ignore them so I have just white spaces. Is there another way than just setting the values smaller than -80 to -80? A way to tell python to plot out-of-range-values too?Holofernes
If you supply vmin and vmax, together with levels, levels will get override. So I guess, np.clip might be useful here. Yes, this's some thing matplotlib does differently, unfortunately.Campball
M
2

I ran into this issue a while back and thought it was a bug (see MPL issue #5055). It's not, but it does require using the extend kwarg, which was non-intuitive to me. Here's what you want to do:

normi = mpl.colors.Normalize(vmin=-80, vmax=20)

cont_PSD = plt.contourf(plotFreq, plotCoord, plotPxx,
                        np.linspace(-80, 20, 200),
                        linestyle=None,
                        norm=normi, extend='both')

plt.colorbar(colbar_PSD)

You can do-away with the plt.clim, colbar_PSD.set_norm and other similar calls.

More examples uses of extend= are available here.

Note that this will create a colorbar with 'triangles' at the top and bottom indicating that the data extends beyond the colorbar, but I think you'll like them once you get used to them, they are descriptive.

Good luck!

Martini answered 22/2, 2016 at 22:42 Comment(3)
Unfortunatelly this has the same effect that just addin adding plt.clim had (plus there are now triangles above und beneath the colorbar^^). :/ But thanks anywayHolofernes
I forgot that you have to specify the levels also. I've fixed the solution (i.e. added np.linspace line).Martini
extend='both' fixed my problem.Cato
J
1

add this after plt.colorbar():

plt.clim(minimal_value, maximal_value)

for the contour plot, add the args vmin and vmax:

cont_PSD = plt.contourf(plotFreq, plotCoord, plotPxx, 200, linestyle=None,vmin=minimal_value,vmax=maximal_value)

You complete code should work like this :

import numpy as np;
import matplotlib as mpl;
import matplotlib.pyplot as plt;
[...]
plotFreq, plotCoord = np.meshgrid(plotFreqVect, plotCoordVect);

figHandler = plt.figure();
cont_PSD = plt.contourf(plotFreq, plotCoord, plotPxx, 200, linestyle=None,vmin=minimal_value,vmax=maximal_value);


plt.colorbar()
plt.clim(minimal_value,maximal_value)
plt.show()
Julide answered 22/2, 2016 at 15:7 Comment(5)
Helped a bit, at least the contour-plot looks like it has the right range, but the colorbar itself has still the wrong ones. Any idea to change that too? But thanks anyway :)Holofernes
Did it, still doesn't work. The damn scale is still set automatically :/Holofernes
Could you add an image of the ouput?Julide
Sure, I've edited the question, there's a picture now :)Holofernes
You should try to set the extend parameter in contourf. from the documentation "extend: [ ‘neither’ | ‘both’ | ‘min’ | ‘max’ ] Unless this is ‘neither’, contour levels are automatically added to one or both ends of the range so that all data are included. These added ranges are then mapped to the special colormap values which default to the ends of the colormap range, but can be set via matplotlib.colors.Colormap.set_under() and matplotlib.colors.Colormap.set_over() methods."Julide

© 2022 - 2024 — McMap. All rights reserved.