I am creating a two-dimensional contour plot with matplotlib. Using the documentation provided http://matplotlib.org/examples/pylab_examples/contour_demo.html, such a contour plot can be created by
import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
# difference of Gaussians
Z = 10.0 * (Z2 - Z1)
plt.figure()
CS = plt.contour(X, Y, Z)
plt.clabel(CS, inline=1, fontsize=10)
plt.title('Simplest default with labels')
which outputs the following plot.
The documentation details how to manually label certain contours (or "lines") on the existing plot. My question is how to create more contour lines than those shown.
For example, the plot shown has two bivariate gaussians. The upper right has three contour lines, at 0.5, 1.0, and 1.5.
How could I add contour lines at say 0.75 and 1.25?
Also, I should be able to zoom in and (in principle) add dozens of dozens of contour lines from (for example) 1.0 and 1.5. How does one do this?
To draw isolines at specified level values, set the levels parameter in .contour:
levels = np.arange(-1.0,1.5,0.25)
CS = plt.contour(X, Y, Z, levels=levels)
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
# difference of Gaussians
Z = 10.0 * (Z2 - Z1)
plt.figure()
levels = np.arange(-1.0,1.5,0.25)
CS = plt.contour(X, Y, Z, levels=levels)
plt.clabel(CS, inline=1, fontsize=10)
plt.title('levels = {}'.format(levels.tolist()))
plt.show()
The sixth figure here uses this method to draw isolines at levels = np.arange(-1.2, 1.6, 0.2).
To zoom in, set the x limits and y limits of the desired region:
plt.xlim(0, 3)
plt.ylim(0, 2)
and to draw, say, 24 automatically-chosen levels, use
CS = plt.contour(X, Y, Z, 24)
For example,
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
# difference of Gaussians
Z = 10.0 * (Z2 - Z1)
plt.figure()
N = 24
CS = plt.contour(X, Y, Z, N)
plt.clabel(CS, inline=1, fontsize=10)
plt.title('{} levels'.format(N))
plt.xlim(0, 3)
plt.ylim(0, 2)
plt.show()
The third figure here uses this method to draw 6 isolines.
Related
When I use contourf, matplotlib chooses to group the values into similar regions and color those regions. How can I make this plot show the full spectrum of different values? In the code below, I want the colors to be continuous, so that sun over the hill is a gradient of increasing colors, instead of these sudden changes in color.
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
import numpy as np
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = 10.0 * (Z2 - Z1)
CS = plt.contourf(X, Y, Z, vmin = 0., vmax = 3., cmap=plt.cm.coolwarm)
plt.show()
A quick workaround would be to make the levels that the contour plot uses very small. Don't use vmin and vmax.
Z = 10.0 * (Z2 - Z1)
clev = np.arange(Z.min(),Z.max(),.001) #Adjust the .001 to get finer gradient
CS = plt.contourf(X, Y, Z, clev, cmap=plt.cm.coolwarm)
plt.show()
EDIT
If you just want the top part more continous play around with the lower and upper bounds of the contour levels.
Z = 10.0 * (Z2 - Z1)
clev = np.arange(0,Z.max(),.001) #Adjust the .001 to get finer gradient
CS = plt.contourf(X, Y, Z, clev, cmap=plt.cm.coolwarm,extend='both')
plt.show()
By definition of the word "contour," contourf plots and fills discrete contours. You may want to consider plt.imshow instead.
plt.imshow(Z, vmin = 0., vmax = 3., cmap=plt.cm.coolwarm, origin='lower',
extent=[X.min(), X.max(), Y.min(), Y.max()])
plt.show()
Hi,
I am trying to create a contour plot with the contours filled with hatches and no color. The following example works if I save it to .png but when I save it to .pdf the output is just the axis.
A code showing what I mean:
import numpy as np
import matplotlib.pyplot as plt
delta = 0.025
x = y = np.arange(-3.0, 3.01, delta)
X, Y = np.meshgrid(x, y)
Z1 = plt.mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = plt.mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = 10 * (Z1 - Z2)
levels=[0,1]
plt.contourf(X, Y, Z/X,
levels,
#alpha=0.5,
colors='none', label='CHECK',
hatches=['\\'])
plt.tight_layout()
plt.savefig('CHECK.pdf')
plt.show()
I checked Matplotlib fill_between() does not save correctly as pdf with hatch and the links within, but no luck fixing the problem!
Perhaps I'm missing something obvious in the documentation,
http://matplotlib.org/examples/pylab_examples/contour_demo.html
but when I first create a contour plot, there are labels for each contour line. However, matplotlib does not do this by default. Using the plot given in the demo, I generate more contour lines between 0.00 and 3.00 :
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
# difference of Gaussians
Z = 10.0 * (Z2 - Z1)
plt.figure()
levels = np.arange(0.00, 3.00, 0.25)
CS = plt.contour(X, Y, Z, levels=levels)
plt.clabel(CS, inline=1, fontsize=10)
plt.xlim(0, 3)
plt.ylim(0, 2)
plt.show()
which outputs
Each contour line is clearly labeled. Now, let's zoom in on a distinct region of this contour, i.e. ((0.5, 1.0), (0.5, 1.0))
plt.figure()
levels = np.arange(0.00, 3.00, 0.25)
CS = plt.contour(X, Y, Z, levels=levels)
plt.clabel(CS, inline=1, fontsize=10)
plt.xlim(0.5, 1.0)
plt.ylim(0.5, 1.0)
plt.show()
This output is clearly NOT labeled.
How can I set plt.contour to automatically label each and every contour line?
You probably need to change x and y directly like so:
x = np.arange(0.5, 1.0, delta)
y = np.arange(0.5, 1.0, delta)
I am finding that manually picking contour labels in matplotlib adds extra lines to the plot. In addition, the contour label is rotated from the local tangent to the contour line. For example, the following code,
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
#Define surface
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
# difference of Gaussians
Z = 10.0 * (Z2 - Z1)
#Plot surface
plt.figure()
CS = plt.contour(X, Y, Z)
#Manually pick labels
CS.clabel(CS.levels, manual = True, inline = True)
with some mouse clicks on the contour lines, results in this plot:
Anyone know what I am doing wrong? Perhaps this is an axes transformation bug…
In case it matters, I am running matplotlib 1.3.0 and python 2.7.5
This is a known bug and there is a fix (PR #2843). This will be fixed in the 1.4 release.
I am trying to overlay a scatter plot onto a contour plot using matplotlib, which contains
plt.contourf(X, Y, XYprof.T, self.nLevels, extent=extentYPY, \
origin = 'lower')
if self.doScatter == True and len(xyScatter['y']) != 0:
plt.scatter(xyScatter['x'], xyScatter['y'], \
s=dSize, c=myColor, marker='.', edgecolor='none')
plt.xlim(-xLimHist, xLimHist)
plt.ylim(-yLimHist, yLimHist)
plt.xlabel(r'$x$')
plt.ylabel(r'$y$')
What ends up happening is the resulting plots extend to include all of the scatter points, which can exceed the limits for the contour plot. Is there any way to get around this?
I used the following example to try and replicate your problem. If left to default, the range for x and y was -3 to 3. I input the xlim and ylim so the range for both was -2 to 2. It worked.
import numpy as np
import matplotlib.pyplot as plt
from pylab import *
# the random data
x = np.random.randn(1000)
y = np.random.randn(1000)
fig = plt.figure(1, figsize=(5.5,5.5))
X, Y = meshgrid(x, y)
Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = 10 * (Z1 - Z2)
origin = 'lower'
CS = contourf(x, y, Z, 10, # [-1, -0.1, 0, 0.1],
cmap=cm.bone,
origin=origin)
title('Nonsense')
xlabel('x-stuff')
ylabel('y-stuff')
# the scatter plot:
axScatter = plt.subplot(111)
axScatter.scatter(x, y)
# set axes range
plt.xlim(-2, 2)
plt.ylim(-2, 2)
show()