how density color cmap array python numpy matplotlib spatial contour

python - density - matplotlib contour plot level



Python: encuentra lĂ­neas de contorno desde matplotlib.pyplot.contour() (2)

Estoy tratando de encontrar (pero no dibujar) líneas de contorno para algunos datos:

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)

Sé que cn contiene las líneas de contorno que quiero, pero parece que no puedo llegar a ellas. He intentado varias cosas:

print dir(cn) pprint(cn.collections[0]) print dir(cn.collections[0]) pprint(cn.collections[0].figure) print dir(cn.collections[0].figure)

en vano. Sé que cn es un ContourSet , y cn.collections es una matriz de LineCollection s. LineCollection que un LineCollection es una matriz de segmentos de línea, pero no puedo averiguar cómo extraer esos segmentos.

Mi objetivo final es crear un archivo KML que traza datos en un mapa del mundo y los contornos de esos datos también.

Sin embargo, dado que algunos de mis puntos de datos están muy juntos, y otros están muy lejos, necesito los polígonos reales (cadenas lineales) que forman los contornos, no solo una imagen rasterizada de los contornos.

Estoy algo sorprendido qhull no hace algo como esto.

Utilizar ListContourPlot de ListContourPlot y luego exportar como SVG funciona, pero quiero usar algo de código abierto.

No puedo usar el conocido algoritmo CONREC porque mis datos no están en una malla (no siempre hay múltiples valores y para un valor x dado, y viceversa).

La solución no tiene que ser python, pero tiene que ser de código abierto y ejecutable en Linux.


Parece que los datos de contorno están en el atributo QuadContourSet objeto QuadContourSet devuelto por la función plt.contour() .

El atributo .allseg es una lista de todos los niveles (que se puede especificar al llamar a plt.contour(X,Y,Z,V) . Para cada nivel, se obtiene una lista de arrays 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'')

En el ejemplo anterior, solo se da un nivel, por lo que len(C.allsegs) = 1. Usted obtiene:

dibujo de contorno

las curvas extraídas


Puede recuperar los vértices haciendo un bucle sobre colecciones y rutas y utilizando el método iter_segments() de matplotlib.path.Path .

Aquí hay una función que devuelve los vértices como un conjunto de listas anidadas de líneas de contorno, secciones de contorno y matrices de vértices 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

Editar:

También es posible calcular los contornos sin trazar nada utilizando el módulo matplotlib._cntr C no matplotlib._cntr :

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