标签3Dplot点+更新

时间:2012-10-15 20:31:52

标签: matplotlib label annotate

我对python和matplotlib很新,这个网站给了我很多帮助。但我找不到关于这个主题的完整答案。

我想使用matplotlib来注释3d图的点,所以经过一些研究后我发现了这个代码的和平: Matplotlib: Annotating a 3D scatter plot

    import pylab
    from mpl_toolkits.mplot3d import Axes3D
    from mpl_toolkits.mplot3d import proj3d
    fig = pylab.figure()
    ax = fig.add_subplot(111, projection = '3d')
    x = y = z = [1, 2, 3]
    sc = ax.scatter(x,y,z)
    # now try to get the display coordinates of the first point

    x2, y2, _ = proj3d.proj_transform(1,1,1, ax.get_proj())

    label = pylab.annotate(
        "this", 
        xy = (x2, y2), xytext = (-20, 20),
        textcoords = 'offset points', ha = 'right', va = 'bottom',
        bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
        arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))

    def update_position(e):
        x2, y2, _ = proj3d.proj_transform(1,1,1, ax.get_proj())
        label.xy = x2,y2
        label.update_positions(fig.canvas.renderer)
        fig.canvas.draw()
    fig.canvas.mpl_connect('button_release_event', update_position)
    pylab.show()

但问题是,我设法只用这段代码更新最后一个标签,我试着在update_position(e)函数中做一些循环。但我肯定错过了一些东西。 到目前为止,我使用了Axes3D.text(x,y,z,s,zdir)函数,但它看起来并不是很好。

谢谢!

1 个答案:

答案 0 :(得分:3)

我最近遇到了同样的问题,我的解决方案的灵感来自以下解决方案:

  1. Matplotlib: Annotating a 3D scatter plot
  2. Annotate several points with one text in matplotlib
  3. 解决方案基于创建“标签”数组,然后在update_position()函数中更新每个“标签”的位置。

    import numpy
    from mpl_toolkits.mplot3d import proj3d
    import matplotlib.pyplot as plt
    import pylab  
    
    def update_position(e):
        print "From update position"
        #Transform co-ordinates to get new 2D projection
        tX, tY, _ = proj3d.proj_transform(dataX, dataY, dataZ, ax.get_proj())
        for i in range(len(dataX)):
            label = labels[i]
            label.xy = tX[i],tY[i]
            label.update_positions(fig.canvas.renderer)
        fig.canvas.draw()
        return
    
    #Input 3D Data
    data = numpy.array([[3,6,2],[4,6,2],[2,9,2],[3,6,10],[6,1,5]])
    
    #Separate into X, Y, Z for greater clarity
    dataX = data[:,0]
    dataY = data[:,1]
    dataZ = data[:,2]
    
    plt.close()
    fig = plt.figure()
    ax = fig.gca(projection='3d')
    
    #3D scatter plot
    ax.scatter(dataX, dataY, dataZ, marker = 'o', c='b')
    
    #Transform co-ordinates to get initial 2D projection
    tX, tY, _ = proj3d.proj_transform(dataX, dataY, dataZ, ax.get_proj())
    
    #Array of labels
    labels = []
    
    #Loop through data points to initially annotate scatter plot
    #and populate labels array
    for i in range(len(dataX)):
        text='['+str(int(dataX[i]))+','+str(int(dataY[i]))+','+str(int(dataZ[i]))+']'
        label = ax.annotate(text,
                xycoords='data',
                xy = (tX[i], tY[i]), xytext = (-20, 20),
                textcoords = 'offset points', ha = 'right', va = 'top', fontsize=6,
                bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
                arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))
        labels.append(label)
    #Positions are updated when mouse button is released after rotation.
    fig.canvas.mpl_connect('button_release_event', update_position)
    fig.show()