15

I have problems with a contour-plot using logarithmic color scaling. I want to specify the levels by hand. Matplotlib, however, draws the color bar in a strange fashion -- the labels are not placed well and only one color appears. The idea is based on http://adversus.110mb.com/?cat=8

Is there anybody out there, who can help me? I use the latest git-repository matplotlib version, v1.1.0 (2011-04-21)

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.mlab import bivariate_normal
from matplotlib.colors import LogNorm
from matplotlib.backends.backend_pdf import PdfPages


delta = 0.5

x = np.arange(-3.0, 4.001, delta)
y = np.arange(-4.0, 3.001, delta)
X, Y = np.meshgrid(x, y)
Z = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)

fig  = plt.figure()
ax   = fig.add_subplot(1,1,1)
#axim = ax.imshow(Z, norm = LogNorm())
axim    = ax.contourf(X,Y,Z,levels=[1e0,1e-1,1e-2,1e-3],cmap=plt.cm.jet,norm = LogNorm())
cb   = fig.colorbar(axim)

pp = PdfPages('fig.pdf')
pp.savefig()
pp.close()


plt.show()

Thank you very much for your help! It works perfect, as you suggested... However, I have another question: Why does matplotlib not allow me to select the number of level lines in the logarithmic mode:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.mlab import bivariate_normal
from matplotlib.colors import LogNorm
from matplotlib.backends.backend_pdf import PdfPages


delta = 0.5

x = np.arange(-3.0, 4.001, delta)
y = np.arange(-4.0, 3.001, delta)
X, Y = np.meshgrid(x, y)
Z = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)

fig  = plt.figure()
ax   = fig.add_subplot(1,1,1)
#axim = ax.imshow(Z, norm = LogNorm())
#axim   = ax.contourf(X,Y,Z,levels=[1e-3,1e-2,1e-1,1e0],cmap=plt.cm.jet,norm = LogNorm())
axim    = ax.contourf(X,Y,Z,20,cmap=plt.cm.jet,norm = LogNorm())
cb   = fig.colorbar(axim)

pp = PdfPages('fig.pdf')
pp.savefig()
pp.close()


plt.show()

https://i.sstatic.net/VeVFQ.png

This was my original problem...

2 Answers 2

17

So it's easily fixed; your order of levels means that the lowest level gets drawn last and therefore covered everything! Try:

axim    = ax.contourf(X,Y,Z,levels=[1e-3, 1e-2, 1e-1, 1e0],cmap=plt.cm.jet,norm = LogNorm())

instead and you should get the desired result.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, worked! - Maybe you can also answer the second question?
@45z23dsa : It seems that the spacing on the LogNorm setting is set to base 10 in the levels - as the data only goes down to ~1e-8 you end you end up with ~8 levels. You can get around this by changing the base yourself. E.g. lev2 = np.arange(np.floor(np.log2(Z.min())-1), np.ceil(np.log2(Z.max())+1) followed by levs = np.power(2, lev_exp) will give you base 2 spaced levels which you can then pass in as the levels argument. However to get exactly, say 20 levels, you need to use a non-standard base.
Dear mutzmatron, Thank you for investigating this! So it is probably easier to simply provide a list of levels which I want... So I consider both questions as being solved!
2

It looks like levels expects increasing values. Try changing them to: levels=[1e-3, 1e-2, 1e-1, 1e0] and see if that solves your issue.

1 Comment

Thanks worked! Maybe you can also answer the second question?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.