matplotlib - 从等高线提取数据

发布于 2024-11-01 13:29:16 字数 1008 浏览 6 评论 0原文

我想从均匀间隔的二维数据(类似图像的数据)的单个轮廓中获取数据。

基于类似问题中找到的示例: 如何获取轮廓绘制的线的 (x,y) 值绘图 (matplotlib)?

>>> import matplotlib.pyplot as plt
>>> x = [1,2,3,4]
>>> y = [1,2,3,4]
>>> m = [[15,14,13,12],[14,12,10,8],[13,10,7,4],[12,8,4,0]]
>>> cs = plt.contour(x,y,m, [9.5])
>>> cs.collections[0].get_paths()

调用 cs.collections[0].get_paths() 的结果是:

[Path([[ 4.          1.625     ]
 [ 3.25        2.        ]
 [ 3.          2.16666667]
 [ 2.16666667  3.        ]
 [ 2.          3.25      ]
 [ 1.625       4.        ]], None)]

根据绘图,这个结果是有意义的,并且似乎是 ( y,x) 对表示轮廓线。

除了手动循环此返回值、提取坐标并组装线条数组之外,是否有更好的方法从 matplotlib.path 对象获取数据?从 matplotlib.path 提取数据时是否有需要注意的陷阱?

或者,在 matplotlib 或更好的 numpy/scipy 中是否有替代方案来执行类似的操作?理想的情况是获得描述该线的 (x,y) 对的高分辨率向量,该向量可用于进一步分析,因为一般来说我的数据集并不像上面的示例那样小或简单。

I would like to get data from a single contour of evenly spaced 2D data (an image-like data).

Based on the example found in a similar question: How can I get the (x,y) values of the line that is ploted by a contour plot (matplotlib)?

>>> import matplotlib.pyplot as plt
>>> x = [1,2,3,4]
>>> y = [1,2,3,4]
>>> m = [[15,14,13,12],[14,12,10,8],[13,10,7,4],[12,8,4,0]]
>>> cs = plt.contour(x,y,m, [9.5])
>>> cs.collections[0].get_paths()

The result of this call into cs.collections[0].get_paths() is:

[Path([[ 4.          1.625     ]
 [ 3.25        2.        ]
 [ 3.          2.16666667]
 [ 2.16666667  3.        ]
 [ 2.          3.25      ]
 [ 1.625       4.        ]], None)]

Based on the plots, this result makes sense and appears to be collection of (y,x) pairs for the contour line.

Other than manually looping over this return value, extracting the coordinates and assembling arrays for the line, are there better ways to get data back from a matplotlib.path object? Are there pitfalls to be aware of when extracting data from a matplotlib.path?

Alternatively, are there alternatives within matplotlib or better yet numpy/scipy to do a similar thing? Ideal thing would be to get a high resolution vector of (x,y) pairs describing the line, which could be used for further analysis, as in general my datasets are not a small or simple as the example above.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

剩一世无双 2024-11-08 13:29:16

对于给定的路径,您可以获得如下点:

p = cs.collections[0].get_paths()[0]
v = p.vertices
x = v[:,0]
y = v[:,1]

For a given path, you can get the points like this:

p = cs.collections[0].get_paths()[0]
v = p.vertices
x = v[:,0]
y = v[:,1]
猫九 2024-11-08 13:29:16

来自: http://matplotlib.org/api/path_api.html#module-matplotlib .路径

Path 对象的用户不应访问顶点和代码数组
直接地。相反,他们应该使用 iter_segments() 来获取
顶点/代码对。这很重要,因为许多 Path 对象作为
优化,根本不存储代码,而是有一个默认代码
由 iter_segments() 为它们提供。

否则,我不太确定你的问题是什么。在处理坐标时,[Zip] 有时是一个有用的内置函数。 1

from: http://matplotlib.org/api/path_api.html#module-matplotlib.path

Users of Path objects should not access the vertices and codes arrays
directly. Instead, they should use iter_segments() to get the
vertex/code pairs. This is important, since many Path objects, as an
optimization, do not store a codes at all, but have a default one
provided for them by iter_segments().

Otherwise, I'm not really sure what your question is. [Zip] is a sometimes useful built in function when working with coordinates. 1

一场信仰旅途 2024-11-08 13:29:16

所有路径的顶点可以简单地通过以下方式返回为 float64 的 numpy 数组:

cs.allsegs[i][j]  # for element j, in level i

其中 cs 的定义如原始问题中所示:

import matplotlib.pyplot as plt
x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
m = [[15, 14, 13, 12], [14, 12, 10, 8], [13, 10, 7, 4], [12, 8, 4, 0]]
cs = plt.contour(x, y, m, [9.5])

更详细:

浏览集合提取路径和顶点并不是最直接或最快的事情。返回的 Contour 对象实际上通过 cs.allsegs 具有段的属性,它返回形状 [level][element][vertex_coord] 的嵌套列表:

num_levels = len(cs.allsegs)
num_element = len(cs.allsegs[0])  # in level 0
num_vertices = len(cs.allsegs[0][0])  # of element 0, in level 0
num_coord = len(cs.allsegs[0][0][0])  # of vertex 0, in element 0, in level 0

请参阅参考:
https://matplotlib.org/stable/api/contour_api.html

The vertices of an all paths can be returned as a numpy array of float64 simply via:

cs.allsegs[i][j]  # for element j, in level i

where cs is defined as in the original question as:

import matplotlib.pyplot as plt
x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
m = [[15, 14, 13, 12], [14, 12, 10, 8], [13, 10, 7, 4], [12, 8, 4, 0]]
cs = plt.contour(x, y, m, [9.5])

More detailed:

Going through the collections and extracting the paths and vertices is not the most straight forward or fastest thing to do. The returned Contour object actually has attributes for the segments via cs.allsegs, which returns a nested list of shape [level][element][vertex_coord]:

num_levels = len(cs.allsegs)
num_element = len(cs.allsegs[0])  # in level 0
num_vertices = len(cs.allsegs[0][0])  # of element 0, in level 0
num_coord = len(cs.allsegs[0][0][0])  # of vertex 0, in element 0, in level 0

See reference:
https://matplotlib.org/stable/api/contour_api.html

爱你是孤单的心事 2024-11-08 13:29:16

我面临着类似的问题,并偶然发现 this matplotlib 列表讨论

基本上,可以去掉绘图并直接调用底层函数,虽然不是超级方便,但也是可能的。该解决方案也不是像素精确的,因为底层代码中可能正在进行一些插值。

import matplotlib.pyplot as plt
import matplotlib._cntr as cntr
import scipy as sp

data = sp.zeros((6,6))
data[2:4,2:4] = 1

plt.imshow(data,interpolation='none')
level=0.5
X,Y = sp.meshgrid(sp.arange(data.shape[0]),sp.arange(data.shape[1]))
c = cntr.Cntr(X, Y, data.T)
nlist = c.trace(level, level, 0)
segs = nlist[:len(nlist)//2]
for seg in segs:
    plt.plot(seg[:,0],seg[:,1],color='white')

plt.show()

I am facing a similar problem, and stumbled over this matplotlib list discussion.

Basically, it is possible to strip away the plotting and call the underlying functions directly, not super convenient, but possible. The solution is also not pixel precise, as there is probably some interpolation going on in the underlying code.

import matplotlib.pyplot as plt
import matplotlib._cntr as cntr
import scipy as sp

data = sp.zeros((6,6))
data[2:4,2:4] = 1

plt.imshow(data,interpolation='none')
level=0.5
X,Y = sp.meshgrid(sp.arange(data.shape[0]),sp.arange(data.shape[1]))
c = cntr.Cntr(X, Y, data.T)
nlist = c.trace(level, level, 0)
segs = nlist[:len(nlist)//2]
for seg in segs:
    plt.plot(seg[:,0],seg[:,1],color='white')

plt.show()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文