157 votes

tracés de surface dans matplotlib

J'ai une liste de 3-tuples représentant un ensemble de points dans un espace 3D. Je veux tracer une surface qui couvre tous ces points.

El plot_surface dans le mplot3d requiert comme arguments X,Y et Z des tableaux de 2d. Est plot_surface la bonne fonction pour tracer la surface et comment transformer mes données dans le format requis ?

data = [(x1,y1,z1),(x2,y2,z2),.....,(xn,yn,zn)]

0 votes

S'il vous plaît, commencez à étiqueter tous ces doublons surface et de fermer les doublons les uns dans les autres. Étiquette également numpy , maille pour celles qui concernent la génération de grilles de maillage.

7voto

Graham G Points 479

J'aimerais ajouter quelques réflexions supplémentaires qui pourraient aider d'autres personnes confrontées à des problèmes de type domaine irrégulier. Pour une situation où l'utilisateur a trois vecteurs/listes, x,y,z représentant une solution 2D où z doit être tracé sur une grille rectangulaire comme une surface, les commentaires 'plot_trisurf()' d'ArtifixR sont applicables. Un exemple similaire, mais avec un domaine non rectangulaire, est le suivant :

import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D 

# problem parameters
nu = 50; nv = 50
u = np.linspace(0, 2*np.pi, nu,) 
v = np.linspace(0, np.pi, nv,)

xx = np.zeros((nu,nv),dtype='d')
yy = np.zeros((nu,nv),dtype='d')
zz = np.zeros((nu,nv),dtype='d')

# populate x,y,z arrays
for i in range(nu):
  for j in range(nv):
    xx[i,j] = np.sin(v[j])*np.cos(u[i])
    yy[i,j] = np.sin(v[j])*np.sin(u[i])
    zz[i,j] = np.exp(-4*(xx[i,j]**2 + yy[i,j]**2)) # bell curve

# convert arrays to vectors
x = xx.flatten()
y = yy.flatten()
z = zz.flatten()

# Plot solution surface
fig = plt.figure(figsize=(6,6))
ax = Axes3D(fig)
ax.plot_trisurf(x, y, z, cmap=cm.jet, linewidth=0,
                antialiased=False)
ax.set_title(r'trisurf example',fontsize=16, color='k')
ax.view_init(60, 35)
fig.tight_layout()
plt.show()

Le code ci-dessus produit :

Surface plot for non-rectangular grid problem

Cependant, cela ne résout pas tous les problèmes, notamment lorsque le problème est défini sur un domaine irrégulier. De plus, dans le cas où le domaine présente une ou plusieurs zones concaves, la triangulation delaunay peut générer des triangles parasites extérieurs au domaine. Dans de tels cas, ces triangles erronés doivent être supprimés de la triangulation afin d'obtenir une représentation correcte de la surface. Pour ces situations, l'utilisateur peut avoir à inclure explicitement le calcul de la triangulation delaunay afin que ces triangles puissent être supprimés de manière programmatique. Dans ces circonstances, le code suivant pourrait remplacer le code de tracé précédent :

import matplotlib.tri as mtri 
import scipy.spatial
# plot final solution
pts = np.vstack([x, y]).T
tess = scipy.spatial.Delaunay(pts) # tessilation

# Create the matplotlib Triangulation object
xx = tess.points[:, 0]
yy = tess.points[:, 1]
tri = tess.vertices # or tess.simplices depending on scipy version

#############################################################
# NOTE: If 2D domain has concave properties one has to
#       remove delaunay triangles that are exterior to the domain.
#       This operation is problem specific!
#       For simple situations create a polygon of the
#       domain from boundary nodes and identify triangles
#       in 'tri' outside the polygon. Then delete them from
#       'tri'.
#       <ADD THE CODE HERE>
#############################################################

triDat = mtri.Triangulation(x=pts[:, 0], y=pts[:, 1], triangles=tri)

# Plot solution surface
fig = plt.figure(figsize=(6,6))
ax = fig.gca(projection='3d')
ax.plot_trisurf(triDat, z, linewidth=0, edgecolor='none',
                antialiased=False, cmap=cm.jet)
ax.set_title(r'trisurf with delaunay triangulation', 
          fontsize=16, color='k')
plt.show()

Des exemples de tracés sont donnés ci-dessous illustrant la solution 1) avec des triangles parasites, et 2) où ils ont été supprimés :

enter image description here

triangles removed

J'espère que ce qui précède pourra être utile aux personnes confrontées à des situations de concavité dans les données de solution.

4voto

qarma Points 3310

Vérifiez l'exemple officiel. X,Y et Z sont en effet des tableaux 2d, numpy.meshgrid() est un moyen simple d'obtenir un maillage x,y 2d à partir de valeurs x et y 1d.

http://matplotlib.sourceforge.net/mpl_examples/mplot3d/surface3d_demo.py

Voici une méthode pythonique pour convertir vos 3-tuples en 3 tableaux de 1d.

data = [(1,2,3), (10,20,30), (11, 22, 33), (110, 220, 330)]
X,Y,Z = zip(*data)
In [7]: X
Out[7]: (1, 10, 11, 110)
In [8]: Y
Out[8]: (2, 20, 22, 220)
In [9]: Z
Out[9]: (3, 30, 33, 330)

Voici la triangulation delaunay de mtaplotlib (interpolation), elle convertit 1d x,y,z en quelque chose de conforme ( ?):

http://matplotlib.sourceforge.net/api/mlab_api.html#matplotlib.mlab.griddata

0 votes

Non... X Y Z sont bidimensionnels dans cet exemple.

0 votes

Je me suis trompé. Utilisez meshgrid() si vos données sont uniformément espacées, comme dans l'exemple lié. Interpoler par exemple avec griddata() si vos données ne sont pas uniformément espacées.

1voto

Evgeni Sergeev Points 1517

Dans Matlab, j'ai fait quelque chose de similaire en utilisant la fonction delaunay sur la fonction x , y uniquement (pas les z ), puis de tracer avec trimesh o trisurf en utilisant z comme la hauteur.

SciPy dispose de la fonction Delaunay qui est basée sur la même bibliothèque sous-jacente QHull que la classe Matlab's delaunay est, vous devriez donc obtenir des résultats identiques.

A partir de là, il suffit de quelques lignes de code pour convertir ceci Tracé de polygones 3D dans python-matplotlib exemple dans ce que vous souhaitez réaliser, comme Delaunay vous donne la spécification de chaque polygone triangulaire.

0 votes

Voir cette réponse sur la base de ax.plot_trisurf(..) .

0voto

lenhhoxung Points 137

Il n'est pas possible de réaliser directement une surface 3D à partir de vos données. Je vous recommande de construire un modèle d'interpolation en utilisant des outils tels que pykridge . Le processus comprendra trois étapes :

  1. Former un modèle d'interpolation en utilisant pykridge
  2. Construire une grille à partir de X y Y en utilisant meshgrid
  3. Interpoler les valeurs pour Z

Après avoir créé votre grille et les Z maintenant vous êtes prêt à aller avec plot_surface . Notez qu'en fonction de la taille de vos données, les meshgrid peut fonctionner pendant un certain temps. La solution de contournement consiste à créer des échantillons régulièrement espacés en utilisant np.linspace para X y Y puis appliquer l'interpolation pour déduire les données nécessaires. Z valeurs. Si c'est le cas, les valeurs interpolées peuvent être différentes des valeurs originales. Z parce que X y Y ont changé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X