I'm trying to find (but not draw!) contour lines for some data:
我试图找到(但不画!)一些数据的等高线:
from pprint import pprint
import matplotlib.pyplot
z = [[0.350087, 0.0590954, 0.002165], [0.144522, 0.885409, 0.378515],
[0.027956, 0.777996, 0.602663], [0.138367, 0.182499, 0.460879],
[0.357434, 0.297271, 0.587715]]
cn = matplotlib.pyplot.contour(z)
I know cn
contains the contour lines I want, but I can't seem to get to them. I've tried several things:
我知道cn包含了我想要的等高线,但我似乎无法找到它们。我试了几件事情:
print dir(cn)
pprint(cn.collections[0])
print dir(cn.collections[0])
pprint(cn.collections[0].figure)
print dir(cn.collections[0].figure)
to no avail. I know cn
is a ContourSet
, and cn.collections
is an array of LineCollection
s. I would think a LineCollection
is an array of line segments, but I can't figure out how to extract those segments.
都无济于事。我知道cn是一个ContourSet,和cn。集合是一系列的linecoll。我认为LineCollection是一系列的线段,但我不知道如何提取这些线段。
My ultimate goal is to create a KML file that plots data on a world map, and the contours for that data as well.
我的最终目标是创建一个KML文件,在世界地图上绘制数据,以及数据的轮廓。
However, since some of my data points are close together, and others are far away, I need the actual polygons (linestrings) that make up the contours, not just a rasterized image of the contours.
然而,由于我的一些数据点是紧密相连的,而另一些距离很远,我需要实际的多边形(linestrings)来组成轮廓,而不仅仅是轮廓的栅格化图像。
I'm somewhat surprised qhull
doesn't do something like this.
我有点惊讶qhull不会做这样的事情。
Using Mathematica's ListContourPlot
and then exporting as SVG works, but I want to use something open source.
使用Mathematica的ListContourPlot,然后导出为SVG,但我想使用一些开放源代码。
I can't use the well-known CONREC algorithm because my data isn't on a mesh (there aren't always multiple y values for a given x value, and vice versa).
我不能使用众所周知的CONREC算法,因为我的数据并不在网格上(给定的x值不总是有多个y值,反之亦然)。
The solution doesn't have to python, but does have to be open source and runnable on Linux.
解决方案不需要python,但必须是Linux上的开源和可运行的。
2 个解决方案
#1
22
You can get the vertices back by looping over collections and paths and using the iter_segments()
method of matplotlib.path.Path
.
您可以通过循环遍历集合和路径并使用matplotlib.path.Path的iter_分段()方法来获得顶点。
Here's a function that returns the vertices as a set of nested lists of contour lines, contour sections and arrays of x,y vertices:
这是一个返回顶点的函数,它是一组嵌套的等高线、等高线和x的数组,y顶点:
import numpy as np
def get_contour_verts(cn):
contours = []
# for each contour line
for cc in cn.collections:
paths = []
# for each separate section of the contour line
for pp in cc.get_paths():
xy = []
# for each segment of that section
for vv in pp.iter_segments():
xy.append(vv[0])
paths.append(np.vstack(xy))
contours.append(paths)
return contours
Edit:
It's also possible to compute the contours without plotting anything using the undocumented matplotlib._cntr
C module:
也可以不使用无文档的matplotlib来计算等值线。_cntr C模块:
from matplotlib import pyplot as plt
from matplotlib import _cntr as cntr
z = np.array([[0.350087, 0.0590954, 0.002165],
[0.144522, 0.885409, 0.378515],
[0.027956, 0.777996, 0.602663],
[0.138367, 0.182499, 0.460879],
[0.357434, 0.297271, 0.587715]])
x, y = np.mgrid[:z.shape[0], :z.shape[1]]
c = cntr.Cntr(x, y, z)
# trace a contour at z == 0.5
res = c.trace(0.5)
# result is a list of arrays of vertices and path codes
# (see docs for matplotlib.path.Path)
nseg = len(res) // 2
segments, codes = res[:nseg], res[nseg:]
fig, ax = plt.subplots(1, 1)
img = ax.imshow(z.T, origin='lower')
plt.colorbar(img)
ax.hold(True)
p = plt.Polygon(segments[0], fill=False, color='w')
ax.add_artist(p)
plt.show()
#2
2
It seems that the contour data is in the .allsegs
attribute of the QuadContourSet
object returned by the plt.contour()
function.
轮廓数据似乎是由plt.contour()函数返回的QuadContourSet对象的.allsegs属性。
The .allseg
attribute is a list of all the levels (which can be specified when calling plt.contour(X,Y,Z,V)
. For each level you get a list of numpy nx2 arrays.
allseg属性是所有级别的列表(可以在调用plt.contour(X,Y,Z,V)时指定。对于每个级别,您将得到一个numpy nx2数组的列表。
plt.figure()
plt.contour(X, Y, Z, [0], colors='r')
plt.figure()
for ii, seg in enumerate(C.allsegs[0]):
plt.plot(seg[:,0], seg[:,1], '.-', label=ii)
plt.legend(fontsize=9, loc='best')
In the above example, only one level is given, so len(C.allsegs)
=1. You get:
在上面的示例中,只给出了一个级别,所以len(C.allsegs) =1。你会得到:
contour plot
等高线图
the extracted curves
提取的曲线
#1
22
You can get the vertices back by looping over collections and paths and using the iter_segments()
method of matplotlib.path.Path
.
您可以通过循环遍历集合和路径并使用matplotlib.path.Path的iter_分段()方法来获得顶点。
Here's a function that returns the vertices as a set of nested lists of contour lines, contour sections and arrays of x,y vertices:
这是一个返回顶点的函数,它是一组嵌套的等高线、等高线和x的数组,y顶点:
import numpy as np
def get_contour_verts(cn):
contours = []
# for each contour line
for cc in cn.collections:
paths = []
# for each separate section of the contour line
for pp in cc.get_paths():
xy = []
# for each segment of that section
for vv in pp.iter_segments():
xy.append(vv[0])
paths.append(np.vstack(xy))
contours.append(paths)
return contours
Edit:
It's also possible to compute the contours without plotting anything using the undocumented matplotlib._cntr
C module:
也可以不使用无文档的matplotlib来计算等值线。_cntr C模块:
from matplotlib import pyplot as plt
from matplotlib import _cntr as cntr
z = np.array([[0.350087, 0.0590954, 0.002165],
[0.144522, 0.885409, 0.378515],
[0.027956, 0.777996, 0.602663],
[0.138367, 0.182499, 0.460879],
[0.357434, 0.297271, 0.587715]])
x, y = np.mgrid[:z.shape[0], :z.shape[1]]
c = cntr.Cntr(x, y, z)
# trace a contour at z == 0.5
res = c.trace(0.5)
# result is a list of arrays of vertices and path codes
# (see docs for matplotlib.path.Path)
nseg = len(res) // 2
segments, codes = res[:nseg], res[nseg:]
fig, ax = plt.subplots(1, 1)
img = ax.imshow(z.T, origin='lower')
plt.colorbar(img)
ax.hold(True)
p = plt.Polygon(segments[0], fill=False, color='w')
ax.add_artist(p)
plt.show()
#2
2
It seems that the contour data is in the .allsegs
attribute of the QuadContourSet
object returned by the plt.contour()
function.
轮廓数据似乎是由plt.contour()函数返回的QuadContourSet对象的.allsegs属性。
The .allseg
attribute is a list of all the levels (which can be specified when calling plt.contour(X,Y,Z,V)
. For each level you get a list of numpy nx2 arrays.
allseg属性是所有级别的列表(可以在调用plt.contour(X,Y,Z,V)时指定。对于每个级别,您将得到一个numpy nx2数组的列表。
plt.figure()
plt.contour(X, Y, Z, [0], colors='r')
plt.figure()
for ii, seg in enumerate(C.allsegs[0]):
plt.plot(seg[:,0], seg[:,1], '.-', label=ii)
plt.legend(fontsize=9, loc='best')
In the above example, only one level is given, so len(C.allsegs)
=1. You get:
在上面的示例中,只给出了一个级别,所以len(C.allsegs) =1。你会得到:
contour plot
等高线图
the extracted curves
提取的曲线