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.
Related
Taking the first example from the matplotlib examples page,
import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
matplotlib.rcParams['xtick.direction'] = 'out'
matplotlib.rcParams['ytick.direction'] = 'out'
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)
# Create a simple contour plot with labels using default colors. The
# inline argument to clabel will control whether the labels are draw
# over the line segments of the contour, removing the lines beneath
# the label
plt.figure()
CS = plt.contour(X, Y, Z)
plt.clabel(CS, inline=1, fontsize=10)
plt.title('Simplest default with labels')
plt.savefig('plot.pgf')
I have the problem that contour labels close to the axes (here, “0.000” at the very top) jut out beyond the figure boundary. Here is the output I get using LaTeX:
As you can see, the label “0.000” at the top overlaps the black line.
Is there anything I can do to fix this? To be clear, my issue is not that the label is close to the axis. What I want is the same behavior as shown on the matplotlib page, namely that the plot content is clipped to the figure area, cutting off text as well as lines.
As shown in the corresponding bug report for matplotlib (#11375), matplotlib’s PGF backend does not support text clipping, which is causing this issue, which still seems to persist today.
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!
I have some 2D data that I am displaying using pcolormesh that I would like to display a few contours on top of. I create the gridded data using
import numpy as np
import matplotlib.pyplot as plt
def bin(x, y, nbins, weights=None):
hist, X, Y = np.histogram2d(x, y, bins=nbins, weights=weights)
x_grid, y_grid = np.meshgrid(X,Y)
return hist, x_grid, y_grid
data = ... # read from binary file
h,x_grid,y_grid = bin(data.x,data.y,512)
# do some calculations with h
h = masked_log(h) # "safe" log that replaces <0 elements by 0 in output
pcm = plt.pcolormesh(x_grid,y_grid,h,cmap='jet')
# Just pretend that the data are lying on the center of the grid
# points, rather than on the edges
cont = plt.contour(x_grid[0:-1,0:-1],y_grid[0:-1,0:-1],h,4,colors='k',origin='lower')
When I plot only the output of pcolormesh, everything looks great. Adding the contours makes a giant mess.
I have read through the contour demo, the API examples, the pcolormesh levels example, and this closely-related SO post (my data is already gridded, so the solution doesn't help). But nothing I have tried thus far has created 4 simple contour lines atop my pcolormesh data.
I've put together minimal example with Gaussian filter (and scipy) which I think looks like it may do what you want. First, set up some dummy data (a Gaussian) and add noise,
import matplotlib
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)
Z = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z += 0.1*np.random.random(Z.shape)
and try to pcolormesh/contour,
plt.figure()
CS = plt.pcolormesh(X, Y, Z)
plt.contour(X, Y, Z, 4, colors='k')
plt.colorbar(CS)
plt.show()
which looks like this,
If we add filtering as follows,
import matplotlib
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
from scipy.ndimage.filters import gaussian_filter
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)
Z = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z += 0.1*np.random.random(Z.shape)
plt.figure()
plt.pcolormesh(X, Y, Z)
CS = plt.contour(X, Y, gaussian_filter(Z, 5.), 4, colors='k',interpolation='none')
plt.colorbar()
plt.show()
it looks much better,
(I've asked the same in MATLAB before)
I'd like to overlay for example a seismic-cmapped contourf-plot (or pcolor) with a grayscale contour-plot, but when I add the latter it also changes the previous colormap. How can this be fixed?
This answer is taken almost entirely from the contour demo example:
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab # for setting up the data
import matplotlib.pyplot as plt
# set up example data:
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)
levels = 10
# plot the filled contour
# using a colormap (jet)
CF = plt.contourf(Z, levels,
extent=(-3,3,-2,2),cmap=cm.jet)
# plot the contour lines
# using gray scale
CL = plt.contour(Z, levels,
linewidths=2,
extent=(-3,3,-2,2),cmap=cm.gray)
# plot color bars for both contours (filled and lines)
CB = plt.colorbar(CL, extend='both')
CBI = plt.colorbar(CF, orientation='horizontal')
# Plotting the second colorbar makes
# the original colorbar look a bit out of place,
# so let's improve its position.
l,b,w,h = plt.gca().get_position().bounds
ll,bb,ww,hh = CB.ax.get_position().bounds
CB.ax.set_position([ll, b, ww, h])
plt.show()
And you'll end up with this plot:
Background
From the documentation example here, one can easily produce the following contour plot with the code snippet.
import matplotlib
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
matplotlib.rcParams['xtick.direction'] = 'out'
matplotlib.rcParams['ytick.direction'] = 'out'
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)
# Create a simple contour plot with labels using default colors. The
# inline argument to clabel will control whether the labels are draw
# over the line segments of the contour, removing the lines beneath
# the label
plt.figure()
CS = plt.contour(X, Y, Z)
plt.clabel(CS, inline=1, fontsize=10)
plt.title('Simplest default with labels')
My Goal
I have obtained my contour plot and meanwhile got the matplotlib.contour.QuadContourSet instance CS. In the example snippet, CS is only used for clabel(). However for my case, I need to obtain either the equation of the contour line or the coordinate set for further computation.
How can I extract the coordinates of the contour line from the instance CS? OR
How can I achieve it in other ways?
I bet there must be a way of doing so. Otherwise, the contour thing is only a "vase for visualization" then.
You can get the coordinates of the contours from the CS.allsegs list.
Try:
dat0= CS.allsegs[0][0]
plt.plot(dat0[:,0],dat0[:,1])
to plot the first (-1) contour level.