在python中使用matplotlib的3D曲面图

时间:2016-08-31 03:37:08

标签: python-2.7 matplotlib

我有三个独立的1-D阵列,包含椭圆体表面的数据点。数据点是通过C代码生成的,并且这些点存储在.CSV文件中。

我想使用matplotlib中的plot_surface函数从这些数据点绘制3D表面。我开始绘制一个三维散点图作为一个健全性检查,以确保我所属的数据点属于一个椭球而不是一些随机的形状。

然后我在matplotlib中尝试了plot_surface()函数,并尝试了迄今为止在SO上讨论过的各种方法,你可以在最后给出的代码中看到它们。我列出了两个输出,因为我的低位代码不允许我发布我的所有结果。

  1. 在matplotlib"中标题为"表面图的帖子, 这导致了输出: surface plot using unique data points for meshgrid 此方法在我的代码 method-4 下实现。我也实现了类似的东西,但没有unique()函数,它再次给了我类似的输出。最后一部分是在我的代码中 method-3 下实现的。
  2. 标题为“#34;在表面上绘制3元组数据点"”的帖子, 这导致了输出: surface plot using grid interpolation over linearly spaced X and Y data points 此部分在代码中 method-2 下实现。
  3. 正如你所看到的,这些方法对我来说都没有用,虽然散点图确认数据点确实属于椭圆体,但表面图给出了错误的结果。

    我做错了吗?如果没有,那么你可以建议一种替代方法来正确绘制我的案例的3D表面吗?我正在使用的数据可以在以下链接中找到:https://drive.google.com/file/d/0BwTffmdLhwB3b0JOMXdHYzFTSGc/view?usp=sharing

    我使用的是python2.7,操作系统:ubuntu-14.04。我是python的新手,所以如果你能提供解释和解决方案,它会很棒。非常感谢你。

    '''
    
    Copyright (c) 2016 Abhishek Agrawal (abhishek.agrawal@protonmail.com)
    Distributed under the MIT License.
    See accompanying file LICENSE.md or copy at http://opensource.org/licenses/MIT
    '''
    
    # Set up modules and packages
    # I/O
    import csv
    from pprint import pprint
    
    # Numerical
    import numpy as np
    import pandas as pd
    from scipy.interpolate import griddata
    import math
    
    # 3D visualization special package
    import mayavi
    from mayavi import mlab
    
    # System
    import sys
    import time
    from tqdm import tqdm
    
    print ""
    print "---------------------------------------------------------------------------------"
    print "                                 NAOS                                            "
    print "                                                                                 "
    print "         Copyright (c) 2016, A. Agrawal (abhishek.agrawal@protonmail.com)        "
    print "---------------------------------------------------------------------------------"
    print ""
    
    # Start timer.
    start_time = time.time( )
    
    # Get plotting packages
    import matplotlib
    import matplotlib.colors
    import matplotlib.axes
    import matplotlib.lines as mlines
    import matplotlib.patches as mpatches
    import matplotlib.pyplot as plt
    import matplotlib.mlab as mlab
    from matplotlib import rcParams
    from matplotlib import cm
    from mpl_toolkits.mplot3d import Axes3D
    from mpl_toolkits.mplot3d import axes3d
    from matplotlib.ticker import LinearLocator, FormatStrFormatter
    import matplotlib.tri as tri
    
    # Operations
    # Read data in csv file. data returned as a panda series.
    data = pd.read_csv( '../data/ellipsoidSurfacePoints.csv' )
    
    # Plot 3D surface of the ellipsoid
    fig = plt.figure()
    ax = fig.gca( projection = '3d' )
    ax.set_xlabel('x [km]')
    ax.set_ylabel('y [km]')
    ax.set_zlabel('z [km]')
    ax.ticklabel_format(style='sci', axis='both', scilimits=(0,0))
    
    x = data['X'].values
    # print x[1:100]
    y = data['Y'].values
    # print y
    z = data['Z'].values
    # print z
    r = np.sqrt( x**2 + y**2 + z**2 )
    
    # **************** trisurf, scatter and wireframe ************ #
    # triang = tri.Triangulation( x, y )
    # ax.plot_trisurf( x, y, z, triangles=triang.triangles, cmap=cm.jet, linewidth=0.1 )
    # ax.scatter( x, y, z )
    # ax.plot_wireframe( x, y, z )
    # plt.show()
    
    # **************** Method - 1 ******************************** #
    # pts = mayavi.mlab.points3d( x, y, z, z )
    # mesh = mayavi.mlab.pipeline.delaunay2d( pts )
    # pts.remove( )
    # surf = mayavi.mlab.pipeline.surface( mesh )
    # mayavi.mlab.show( )
    
    # **************** Method - 2 ******************************** #
    # x1 = np.linspace( x.min(), x.max() )
    # y1 = np.linspace( y.min(), y.max() )
    # xx, yy = np.meshgrid( x1, y1 )
    # zz = griddata( ( x, y ), z, ( x1, y1 ), method='cubic' )
    # ax.plot_surface( xx, yy, zz, rstride=5, cstride=5, cmap=cm.jet, linewidth=0.1, antialiased=False )
    # plt.show()
    
    # **************** Method - 3 ******************************** #
    x1 = np.linspace( x.min(), x.max() )
    y1 = np.linspace( y.min(), y.max() )
    xx, yy = np.meshgrid( x1, y1 )
    zz = griddata( ( x, y ), z, ( xx, yy ), method='cubic' )
    ax.plot_surface( xx, yy, zz, rstride=5, cstride=5, cmap=cm.jet, linewidth=0.1, antialiased=False )
    plt.show()
    
    # **************** Method - 4 ******************************** #
    # x1 = np.linspace( x.min(), x.max(), len( data['X'].unique() ) )
    # y1 = np.linspace( y.min(), y.max(), len( data['Y'].unique() ) )
    # xx, yy = np.meshgrid( x1, y1 )
    # zz = griddata( ( x, y ), z, ( xx, yy ), method='cubic' )
    # ax.plot_surface( xx, yy, zz, rstride=5, cstride=5, cmap=cm.jet, linewidth=0.1, antialiased=False )
    # plt.show()
    
    # **************** Method - 5 ******************************** #
    # xx, yy = np.mgrid[ min(x):max(x):100j, min(y):max(y):100j ]
    # zz = griddata( ( x, y ), z, ( xx, yy ), method='cubic' )
    # ax.plot_surface( xx, yy, zz, rstride=5, cstride=5, cmap=cm.jet, linewidth=0.1, antialiased=False )
    # plt.show()
    
    # Stop timer
    end_time = time.time( )
    
    # Print elapsed time
    print "Script time: " + str("{:,g}".format(end_time - start_time)) + "s"
    
    print ""
    print "------------------------------------------------------------------"
    print "                         Exited successfully!                     "
    print "------------------------------------------------------------------"
    print ""
    

1 个答案:

答案 0 :(得分:1)

我认为您正在寻找的是plot_trisurf,它可以处理非结构化一维数据。下面的代码使用您的数据进行绘制。数据的关键问题是每个X / Y点都有3个z值,plot_trisurf无法自动处理(尽管有很多解决方法,例如,请参见有关绘制球体的问题)。我已经通过将复制的X / Y点拆分为单独的数据帧来解决此问题。

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import pandas as pd

fileDir = "data.csv"

data = pd.read_csv(fileDir, engine = 'c', float_precision = 'round_trip', dtype=np.float64)

dataTop = data.drop_duplicates(subset=['x', 'y'], keep='first', inplace=False)
XTop = dataTop['x']
YTop = dataTop['y']
ZTop = dataTop['z']

dataMid = data.drop_duplicates(subset=['x', 'y'], keep=False, inplace=False)
XMid = dataMid['x']
YMid = dataMid['y']
ZMid = dataMid['z']

dataBottom = data.drop_duplicates(subset=['x', 'y'], keep='last', inplace=False)
XBottom = dataBottom['x']
YBottom = dataBottom['y']
ZBottom = dataBottom['z']

fig = plt.figure(figsize=(11.5, 8.5))
ax = fig.add_subplot(111, projection='3d')

ax.plot_trisurf(XTop, YTop, ZTop, cmap='viridis', alpha=0.5)
ax.plot_trisurf(XMid, YMid, ZMid, cmap='viridis', alpha=0.5)
ax.plot_trisurf(XBottom, YBottom, ZBottom, cmap='viridis', alpha=0.5)

plt.show()

all plotted

如果您可以告诉我更多有关情节的信息,请期待,我可以尝试更具体一些。有关三角剖分的更多信息,请参见Matplotlib like matlab's trisurf