matplotlib bar3d clipping problems - python

I am trying to create a 3D bar graph with Matplotlib 1.2.0 and Python 2.7.3. I followed the advice in http://www.mail-archive.com/matplotlib-users#lists.sourceforge.net/msg19740.html and plotted the bar one by one, but I am still getting rendering problems (i.e., bars on top of each other).
Moreover, I get the following when I invoke my code:
/usr/apps/python/lib/python2.7/site-packages/mpl_toolkits/mplot3d/axes3d.py:1476: RuntimeWarning: divide by zero encountered in divide for n in normals])
/usr/apps/python/lib/python2.7/site-packages/mpl_toolkits/mplot3d/axes3d.py:1476: RuntimeWarning: invalid value encountered in divide for n in normals])
My questions:
Are these serious warnings? Do I need to look into them and try to
eliminate them? How do I eliminate them?
What is the difference between zsort='max' and zsort='average'?
What else can I do to eliminate rendering problems?
Thanks in advance!
Here is my code:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.colors as colors
import matplotlib.cm as cmx
# my data
dat = [2.31778665482167e-310, 0.006232785101850947, 0.0285075971030949, 0.0010248181570355695, 0.0048776795767614825, 0.02877090365176044, 0.002459331469834533, 0.0008594610645495889, 0.002919824084878003, 0.000968081117692596, 0.0, 0.0, 0.0319623949119874, 0.00568752311279771, 0.009994801469036968, 0.03248018520506219, 0.006686905726805326, 0.005987863156039365, 0.0072955095915350045, 0.005568911905473998, 0.0, 0.0, 0.0, 0.028483143996551524, 0.031030793902192794, 0.06125216053962635, 0.02935971973938871, 0.028507530280092265, 0.030112963748812088, 0.028293406731749605, 0.0, 0.0, 0.0, 0.0, 0.004510645022825792, 0.028998119822468988, 0.0013993630391143715, 0.0010726572949244424, 0.002288215944285159, 0.0006513973584945584, 0.0, 1.1625e-320, 1.15348834e-316, 2.3177866547513e-310, 0.0, 0.03148966953869102, 0.005215047563268979, 0.004491716298086729, 0.006010166308872446, 0.005186976949223524, 0.0, 0.0, 0.0, 0.0, 0.0, 1.107e-320, 0.02983657915729719, 0.028893006725328373, 0.030526067389954753, 0.028629390713739978, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0015217840289869456, 0.002751587509779179, 0.001413669523724954, 1.15348834e-316, 2.3177866547513e-310, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0024680339073824705, 0.0008254364860386303, 0.0, 0.0, 0.0, 9.965e-321, 1.15348834e-316, 2.3177866547513e-310, 0.0, 0.0, 0.0, 0.002621588539481613, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.41e-321, 1.15348834e-316, 2.3177866547513e-310]
dat = np.reshape(dat,[10,10],order='F')
lx = len(dat[0])
ly = len(dat[:,0])
n = lx*ly
# generate colors
cm = plt.get_cmap('jet')
vv = range(len(dat))
cNorm = colors.Normalize(vmin=0, vmax=vv[-1])
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=cm)
colorVals = [scalarMap.to_rgba(i) for i in range(ly)]
# generate plot data
xpos = np.arange(0,lx,1)
ypos = np.arange(0,ly,1)
xpos, ypos = np.meshgrid(xpos+0.25, ypos+0.25)
xpos = xpos.flatten()
ypos = ypos.flatten()
zpos = np.zeros(n)
dx = 0.5*np.ones_like(zpos)
dy = dx.copy()
dz = dat.flatten()
cc = np.tile(range(lx), (ly,1))
cc = cc.T.flatten()
# generate plot
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
opacity = 1
for i in range(n):
ax.bar3d(xpos[i], ypos[i], zpos[i], dx[i], dy[i], dz[i],
color=colorVals[cc[i]], alpha=opacity, zsort='max')
plt.autoscale(enable=True, axis='both', tight=True)
plt.grid()
plt.show(block=False)

This isn't the answer that you are looking for, but I think that this might be a bug in matplotlib. I think that the same problem was encountered here. The problem was described as "intractable" according to the mplot3d FAQ.
But to me it doesn't seem intractable. You simple need to figure out which object is closer to the viewer and set the z-order accordingly. So, I think that the problem might just be a bug.
If I take the matplotlib 3D histogram example and just change "bins=4" to "bins=6" or a higher number, then I get the same "axes3d.py:1476: RuntimeWarning: invalid value encountered in divide / for n in normals])". Also, I can reproduce the wrong z-order of the bars (check out the tall guy near the front who jumps in front of his short friend):
The incorrect ordering of the bars seems linked to the divide by zero error, since the plots look just fine when I use a smaller number of bins.
Line 1476 in axes.py is:
shade = np.array([np.dot(n / proj3d.mod(n), [-1, -1, 0.5]) for n in normals])
Basically, I think it is trying to figure out the shading using the normal vectors to each face. But, one or more of the normal vectors is zero, which should not be the case. So, I think that this is just some bug in matplotlib that can probably be fixed by someone with more programming skills than myself.
The mplot3d FAQ is correct that MayaVI can be used if you want a better 3D engine. I used
from mayavi import mlab
mlab.barchart(xpos,ypos,dz*100)
to generate a plot of your data:
I hope that this gets figured out soon. I would like to make some similar 3D barcharts in the near future.

This answer is a quick fix solution that allows you to produce certain types of 3D bar charts in matplotlib with correct rendering. The trick is to A) plot the bars individually, B) hack the zsort algorithm to force sorting the bars w.r.t. the "distance" from the camera. This can be done by overwrite the _sort_zpos attribute of the PolyCollection3D instance returned by ax.bar3d. The following code demonstrates the solution using data drawn from a 2D Gaussian.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from scipy.stats import multivariate_normal
def sph2cart(r, theta, phi):
'''spherical to cartesian transformation.'''
x = r * np.sin(theta) * np.cos(phi)
y = r * np.sin(theta) * np.sin(phi)
z = r * np.cos(theta)
return x, y, z
def sphview(ax):
'''returns the camera position for 3D axes in spherical coordinates'''
r = np.square(np.max([ax.get_xlim(), ax.get_ylim()], 1)).sum()
theta, phi = np.radians((90-ax.elev, ax.azim))
return r, theta, phi
def ravzip(*itr):
'''flatten and zip arrays'''
return zip(*map(np.ravel, itr))
#Generate data
res = 15
sl = slice(-3, 3, complex(res))
Y, X = np.mgrid[sl, sl]
grid = np.array([X, Y])
(dx,), (dy,) = 0.8*np.diff(X[0,:2]), 0.8*np.diff(Y[:2,0])
#2D Gaussian
mu = (0, 0)
covm = np.array([[ 0.8, 0.3],
[ 0.3, 0.5]])
rv = multivariate_normal(mu, covm)
Zg = rv.pdf(grid.transpose(1,2,0)).T
#generate the figure
fig, (ax1, ax2) = plt.subplots(1,2, subplot_kw=dict(projection='3d'))
#standard bar3d
ax1.set_title('Standard')
ax1.bar3d(X.ravel(), Y.ravel(), np.zeros(X.size), dx, dy, Zg.ravel(), '0.85')
#Fixed bar3d
ax2.set_title('Fixed')
xyz = np.array(sph2cart(*sphview(ax2)), ndmin=3).T #camera position in xyz
zo = np.multiply([X, Y, np.zeros_like(Zg)], xyz).sum(0) #"distance" of bars from camera
bars = np.empty(X.shape, dtype=object)
for i, (x,y,dz,o) in enumerate(ravzip(X, Y, Zg, zo)):
j, k = divmod(i, res)
bars[j, k] = pl = ax2.bar3d(x, y, 0, dx, dy, dz, '0.85')
pl._sort_zpos = o
plt.show()
Which produces the following figure:
Note: This will only work for the initial viewing angle. If you rotate the axes, you will have to set the _sort_zpos for all the bars again and redraw the canvas to fix the rendering.

I took apodemus's code, which apparently works, unpacked it, and applied it to the original question to provide a direct answer for it. My code could certainly be cleaned up - particularly the loop in getDistances() - but it does solve the presented problem, and should be much easier to follow. To surmise, the distance to the viewer, i.e., the camera distance, has to be determined by calling sphview() and sph2cart(). Then the distances of all of the bars from the camera must be calculated by calling getdistances(). Thereafter, the bars should be drawn one and a time, and crucially, each bar's z-order must be explicitly set based on the previously determined distances.
If the resultant graph is rotated live in the plot window, it may not be updated correctly. However, presetting the location of the camera allows arbitrary initial views to be plotted without error. (There may well be a callback mechanism that could be invoked to cause the z-orders of the bars to be explicitly recalculated, but I have no knowledge of such an API.) The location of the camera can be preset by passing azim and elev to fig.add_subplot(). Its distance can be changed by setting the dist field of the Axes instance returned by fig.add_subplot().
Following is the graph produced by the updated code applied to the original question:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.colors as colors
import matplotlib.cm as cmx
# from apodemus's Stackoverflow answer,
# https://stackoverflow.com/questions/18602660/matplotlib-bar3d-clipping-problems
def sph2cart(r, theta, phi):
'''spherical to Cartesian transformation.'''
x = r * np.sin(theta) * np.cos(phi)
y = r * np.sin(theta) * np.sin(phi)
z = r * np.cos(theta)
return x, y, z
def sphview(ax):
'''returns the camera position for 3D axes in spherical coordinates'''
r = np.square(np.max([ax.get_xlim(), ax.get_ylim()], 1)).sum()
theta, phi = np.radians((90-ax.elev, ax.azim))
return r, theta, phi
#
# end of apodemus's code
def getDistances(view):
distances = []
a = np.array((xpos, ypos, dz))
for i in range(len(xpos)):
distance = (a[0, i] - view[0])**2 + (a[1, i] - view[1])**2 + (a[2, i] - view[2])**2
distances.append(np.sqrt(distance))
return distances
# ================================================================
# my data
dat = [2.31778665482167e-310, 0.006232785101850947, 0.0285075971030949, 0.0010248181570355695, 0.0048776795767614825, 0.02877090365176044, 0.002459331469834533, 0.0008594610645495889, 0.002919824084878003, 0.000968081117692596, 0.0, 0.0, 0.0319623949119874, 0.00568752311279771, 0.009994801469036968, 0.03248018520506219, 0.006686905726805326, 0.005987863156039365, 0.0072955095915350045, 0.005568911905473998, 0.0, 0.0, 0.0, 0.028483143996551524, 0.031030793902192794, 0.06125216053962635, 0.02935971973938871, 0.028507530280092265, 0.030112963748812088, 0.028293406731749605, 0.0, 0.0, 0.0, 0.0, 0.004510645022825792, 0.028998119822468988, 0.0013993630391143715, 0.0010726572949244424, 0.002288215944285159, 0.0006513973584945584, 0.0, 1.1625e-320, 1.15348834e-316, 2.3177866547513e-310, 0.0, 0.03148966953869102, 0.005215047563268979, 0.004491716298086729, 0.006010166308872446, 0.005186976949223524, 0.0, 0.0, 0.0, 0.0, 0.0, 1.107e-320, 0.02983657915729719, 0.028893006725328373, 0.030526067389954753, 0.028629390713739978, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0015217840289869456, 0.002751587509779179, 0.001413669523724954, 1.15348834e-316, 2.3177866547513e-310, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0024680339073824705, 0.0008254364860386303, 0.0, 0.0, 0.0, 9.965e-321, 1.15348834e-316, 2.3177866547513e-310, 0.0, 0.0, 0.0, 0.002621588539481613, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.41e-321, 1.15348834e-316, 2.3177866547513e-310]
dat = np.reshape(dat,[10,10],order='F')
lx = len(dat[0])
ly = len(dat[:,0])
n = lx*ly
# generate colors
cm = plt.get_cmap('jet')
vv = range(len(dat))
cNorm = colors.Normalize(vmin=0, vmax=vv[-1])
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=cm)
colorVals = [scalarMap.to_rgba(i) for i in range(ly)]
# generate plot data
xpos = np.arange(0,lx,1)
ypos = np.arange(0,ly,1)
xpos, ypos = np.meshgrid(xpos+0.25, ypos+0.25)
xpos = xpos.flatten()
ypos = ypos.flatten()
zpos = np.zeros(n)
dx = 0.5*np.ones_like(zpos)
dy = dx.copy()
dz = dat.flatten()
cc = np.tile(range(lx), (ly,1))
cc = cc.T.flatten()
# generate plot
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
opacity = 1
# Get the camera's location in Cartesian coordinates.
x1, y1, z1 = sph2cart(*sphview(ax))
camera = np.array((x1,y1,0))
# Calculate the distance of each bar from the camera.
z_order = getDistances(camera)
max = max(z_order)
for i in range(n):
pl = ax.bar3d(xpos[i], ypos[i], zpos[i], dx[i], dy[i], dz[i],
color=colorVals[cc[i]], alpha=opacity, zsort='max')
# The z-order must be set explicitly.
#
# z-order values are somewhat backwards in magnitude, in that the largest
# value is closest to the camera - unlike, in say, a coordinate system.
# Therefore, subtracting the maximum distance from the calculated distance
# inverts the z-order to the proper form.
pl._sort_zpos = max - z_order[i]
plt.autoscale(enable=True, axis='both', tight=True)
plt.grid()
plt.show()
This approach (as opposed to using Mayavi to handle 3D drawing, for example) allows the matplotlib appearance to be retained in the graph itself, as well as its adornments such as axes numbers, labels, and legends.

I think marisano 's answer has a problem of rendering with various height because it uses the Euclidean distance from the top of a bar to the camera position and substract this value from maximal z_order, I don't think it is the correct way. Finally I adopt the same measurement of z_order from apodemus and updated it below:
z_order = np.multiply([xpos,ypos, np.zeros_like(xpos)],camera).sum(0)
and
pl._sort_zpos = z_order[i]
Now it works in my case.

Related

How add interactions to bokeh spider-chart (radar-chart)

I'm trying to make an interactive spider chart using Bokeh.
The chart it's almost done, there are only a couple of things missing that even with the documentation I'm not able to get. In particular I would like to have a label that come out when I pass the mouse over a zone (eg: for the "yellow area" I would like to see its count values for each vertex with the vertex name). Finally the last problem is that my chart polygon is missing the edge connecting the first and last vertex.
I leave here my code with a sample of the data I'm using, thank you for the help.
import numpy as np
import pandas as pd
import math
from bokeh.io import output_file, show
from bokeh.models import BasicTicker, ColorBar, LinearColorMapper, ColumnDataSource, PrintfTickFormatter, LabelSet, Legend, HoverTool
from bokeh.plotting import figure
from bokeh.transform import transform
from bokeh.palettes import viridis
mod_cat_ID = pd.DataFrame(columns=['ID','Name'])
mod_cat_ID['ID'] = [1,2,3,4,5,6,7,8,9,10,'X','?']
mod_cat_ID['Name'] = ['Carbohydrate metabolism','Energy metabolism','Lipid metabolism','Nucleotide metabolism','Amino acid metabolism','Glycan metabolism','Metabolism of cofactors and vitamins','Biosynthesis of terpenoids and polyketides','Biosynthesis of other secondary metabolites','Xenobiotics biodegradation','Signature Modules','Unknown']
df=pd.DataFrame(columns=['Pheno_ID','Genes_count','Norm_count'])
df['Pheno_ID'] = ['MP:0000218','MP:0000321','MP:0010093','MP:0001985','MP:0011094']
df['Genes_count'] = [[689, 248, 476, 97, 0, 800, 0, 0, 0, 0],[0, 0, 180, 0, 0, 0, 236, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],[120, 0, 0, 0, 88, 0, 0, 0, 0, 0],[367, 600, 347, 240, 361, 404, 236, 0, 0, 0]]
df['Norm_count'] = [[0.86125, 0.31, 0.595, 0.12125, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],[0.0, 0.0, 0.225, 0.0, 0.0, 0.0, 0.295, 0.0, 0.0, 0.0],[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],[0.15, 0.0, 0.0, 0.0, 0.11, 0.0, 0.0, 0.0, 0.0, 0.0],[0.45875, 0.75, 0.43375, 0.3, 0.45125, 0.505, 0.295, 0.0, 0.0, 0.0]]
#The last 2 categories are not counted and showed
n_vertex = len(mod_cat_ID) - 2
theta = np.linspace(0, 2 * np.pi, n_vertex, endpoint=False)
# rotate theta such that the first axis is at the top
theta += np.pi / 2
centre = 1
def unit_poly_verts(theta, centre):
"""Return vertices of polygon for subplot axes.
This polygon is circumscribed by a unit circle centered at (centre, centre)
"""
x0, y0, r = [centre] * 3
verts = [(r * np.cos(t) + x0, r * np.sin(t) + y0) for t in theta]
return verts
def radar_patch(r, theta, centre):
""" Returns the x and y coordinates corresponding to the magnitudes of
each variable displayed in the radar plot
"""
# offset from centre of circle
offset = 0
yt = (r * centre + offset) * np.sin(theta) + centre
xt = (r * centre + offset) * np.cos(theta) + centre
return xt, yt
verts = unit_poly_verts(theta, centre)
x = [v[0] for v in verts]
y = [v[1] for v in verts]
fig = figure(title="Phenotype/Pathway module - Radar plot")
#Here I need only the first 10 categories, the last 2 are not counted and showed
text = mod_cat_ID['Name'][0:10]
source = ColumnDataSource({'x': x , 'y': y , 'text': text})
fig.line(x="x", y="y", source=source)
labels = LabelSet(x="x", y="y", text="text", source=source)
fig.add_layout(labels)
cols = viridis(len(df))
for i in range(len(df)):
xt, yt = radar_patch(np.asarray(df['Norm_count'][i]), theta, centre)
fig.patch(x=xt, y=yt, fill_alpha=0.15, fill_color=cols[i], line_color=cols[i], legend_label=str(df['Pheno_ID'][i]))
fig.circle([centre],[centre], color = 'black')
fig.axis.visible = False
fig.xgrid.grid_line_color = None
fig.ygrid.grid_line_color = None
fig.legend.location = 'top_left'
fig.legend.click_policy = 'hide'
show(fig)

stackplot with different x data

Stacked plotting in matplotlib with equal x data is as easy as
from matplotlib import pyplot as plt
x0 = [0.0, 0.5, 2.0]
y0 = [1.0, 1.5, 1.0]
# x1 = [0.0, 1.5, 2.0]
y1 = [1.0, 1.5, 1.0]
plt.stackplot(x0, (y0, y1))
plt.show()
Is it possible to stack two plots with different x data too?
It does not seem to be possible. If you look at the code for Matplotlib's stackplot, then this is the part that draws the stacked plot itself:
# Color between array i-1 and array i
for i in xrange(len(y) - 1):
color = axes._get_lines.get_next_color()
r.append(axes.fill_between(x, stack[i, :], stack[i + 1, :],
facecolor=color,
label= six.next(labels, None),
**kwargs))
So it will always use the same x for all stacks.
You could on the other hand create a new x array for the stacked plot, and include all values from all the different x arrays you have, and then calculate the missing y stack values using linear interpolation.
A possible solution using interpolation could look like this:
from matplotlib import pyplot as plt
def interp_nans(x, y):
is_nan = np.isnan(y)
res = y * 1.0
res[is_nan] = np.interp(x[is_nan], x[-is_nan], y[-is_nan])
return res
x = np.array([0.0, 0.5, 1.5, 2.0])
y0 = np.array([1.0, 1.5, np.nan, 1.0])
y1 = np.array([1.0, np.nan, 1.5, 1.0])
plt.stackplot(x, (interp_nans(x, y0), interp_nans(x, y1)))
plt.show()
But if interpolation can not be used in this case, then it would not work.

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