matplotlib PGF output: Contour labels extend beyond figure boundary - python

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.

Related

Hatches filling an empty color contour not saved in pdf python matplotlib

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!

Location of contour lines

Below is my code and plot:
import matplotlib
import matplotlib.mlab as mlab
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
delta = 0.00025
A=0
x = np.arange(0, 0.10, delta)
y = np.arange(0, 0.1, delta)
X, Y = np.meshgrid(x, y)
Z = A*(X**2+Y**2)+2*X*Y
manual_locations = [(0.1,0.1), (0.2,0.2), (0.3,0.3),
(0.015, 0.015), (0.00255, 0.0025), (0.00005,0.00005)]
line_widths = (1, 1, 1, 1, 1, 1)
plt.figure()
CS = plt.contour(X, Y, Z, 6, # add 6 contour lines
linewidths=line_widths, # line widths
colors = line_colours) # line colours
plt.clabel(CS, inline=1, # add labels
fontsize=10, # label font size
manual=manual_locations) # label locations
plt.title('Indifference Map') # title
plt.show()
It seems my manual_locations does nothing, python picks equally spaced contour lines automatically. While I want to investigate more details around 0. How can I see more curves/contour lines converging to (0,0)?
Thanks in advance.
The easiest way to explore parts of your data in more details is with levels. This sets what Z-values to examine, and in your question you phrase this as an (x,y) location to inspect, but it's a bit backwards from how contour works to specify the location points directly.
You could also do inspect the (0,0) region by changing the boundaries of the plot appropriately.
Below, I use log values for levels, but linear values work equally well, are far more common, and are easier to interpret. The log values just easily emphasis the part of the plot you're most interested in.
import matplotlib
import matplotlib.mlab as mlab
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import numpy as np
#%matplotlib inline
delta = 0.00025
A=0
x = np.arange(0, 0.10, delta)
y = np.arange(0, 0.1, delta)
X, Y = np.meshgrid(x, y)
Z = A*(X**2+Y**2)+2*X*Y
manual_locations = [(0.1,0.1), (0.2,0.2), (0.3,0.3),
(0.015, 0.015), (0.00255, 0.0025), (0.00005,0.00005)]
line_widths = (1, 1, 1, 1, 1, 1)
plt.figure()
CS = plt.contour(X, Y, Z, 6, # add 6 contour lines
linewidths=line_widths,
#levels=np.linspace(0, .003, 20))
levels=np.logspace(-5, -2, 20))
plt.clabel(CS, inline=1, # add labels
fontsize=10,
fmt="%.5f")
plt.title('Indifference Map') # title
plt.show()
If you really need the contour at a specific location, you could put the (x,y) values for that location into your equation to calculate the z-value at that location, and then use this value as one of the values in the levels argument.

How to overlay a controuf plot with a differently colored contour plot?

(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:

matplotlib: manually (interactively) picked contour label adds extra lines

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.

Get coordinates from the contour in matplotlib?

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.

Categories