web-dev-qa-db-fra.com

matplotlib - extraire des données des courbes de niveau

Je souhaite obtenir des données à partir d'un seul contour de données 2D régulièrement espacées (des données de type image).

Basé sur l'exemple trouvé dans une question similaire: Comment puis-je obtenir les valeurs (x, y) de la ligne qui est tracée par un tracé de contour (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()

Le résultat de cet appel dans cs.collections[0].get_paths() est:

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

Sur la base des graphiques, ce résultat est logique et semble être une collection de paires (y, x) pour la ligne de contour.

Outre le bouclage manuel de cette valeur de retour, l'extraction des coordonnées et l'assemblage des tableaux pour la ligne, existe-t-il de meilleures façons de récupérer les données d'un objet matplotlib.path? Y a-t-il des pièges à connaître lors de l'extraction de données d'un matplotlib.path?

Sinon, existe-t-il des alternatives dans matplotlib ou mieux encore numpy/scipy pour faire une chose similaire? L'idéal serait d'obtenir un vecteur haute résolution de paires (x, y) décrivant la ligne, qui pourrait être utilisé pour une analyse plus approfondie, car en général mes ensembles de données ne sont pas aussi petits ou simples que l'exemple ci-dessus.

50
dtlussier

Pour un chemin donné, vous pouvez obtenir les points comme ceci:

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

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

Les utilisateurs d'objets Path ne doivent pas accéder directement aux tableaux de sommets et de codes. Au lieu de cela, ils devraient utiliser iter_segments () pour obtenir les paires vertex/code. Ceci est important, car de nombreux objets Path, en tant qu'optimisation, ne stockent pas du tout de codes, mais en ont un par défaut fourni par iter_segments ().

Sinon, je ne suis pas vraiment sûr de votre question. [Zip] est une fonction intégrée parfois utile lorsque vous travaillez avec des coordonnées. 1

9
Permafacture

Je suis confronté à un problème similaire et je suis tombé sur cette discussion sur la liste matplotlib .

Fondamentalement, il est possible de supprimer le tracé et d'appeler directement les fonctions sous-jacentes, ce n'est pas super pratique, mais c'est possible. La solution n'est pas non plus précise en pixels, car il y a probablement une interpolation en cours dans le code sous-jacent.

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()
4
grg rsr

Les sommets de tous les chemins peuvent être retournés sous forme de tableau numpy de float64 simplement via:

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

Plus détaillé:

Parcourir les collections et extraire les chemins et les sommets n'est pas la chose la plus simple ou la plus rapide à faire. L'objet Contour retourné a en fait des attributs pour les segments via cs.allsegs, qui renvoie une liste imbriquée de forme [niveau] [élément] [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

Voir référence: https://matplotlib.org/3.1.1/api/contour_api.html

0
RCCG