0

My current code does not yield the expected result:

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
colors = cm.rainbow(np.linspace(0, 1, len(gt_x)))
for i in range(len(gt_x)):
    ax.scatter(gt_x[i], gt_y[i], gt_z[i], s=50, marker='o', c=colors[i], label='gt')
    ax.scatter(pred_x[i], pred_y[i], pred_z[i], s=50, marker='x', c=colors[i], label='predicted')
    fig.canvas.draw()
    data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep="")
    data = data.reshape(fig.canvas.get_width_height()[::-1] + (3,))
    imgs.append([plt.imshow(data, animated=True)])

clip = animation.ArtistAnimation(fig, imgs, interval=100, blit=False, repeat_delay=1000)
name = os.path.join("../data", "scatter_plot") + ".gif"
clip.save(name, writer='imagemagick')

I want to use the same logic, i.e. adding 3d points to my scatter plot iteratively, with a FuncAnimation and offsets which seems to be the correct way to do what I want.

However, this involves using 3D offsets and ax update functions which I do not know how to use for this purpose since many functions seem to be private and thus not documented, e.g. ax._3doffsets().

whiletrue
  • 10,500
  • 6
  • 27
  • 47
  • 2
    Did you see [this answer](https://stackoverflow.com/questions/41602588/matplotlib-3d-scatter-animations)? `._offsets3d` is indeed private. Feel free to open an issue to ask for it to become public or directly submit a PR. – ImportanceOfBeingErnest Feb 20 '19 at 12:35
  • Thank you for sharing the link. That is indeed very helpful. Looking at the code in your answer: How can one change the marker style & color in each update per point? I cannot find examples for that. Thanks! – whiletrue Feb 21 '19 at 01:33
  • 1
    [here is](https://stackoverflow.com/questions/52634390/matplotlib-change-color-of-point-in-3d-scatter-plot-onpick) for color. The markerstyle should be similar to the 2D case. – ImportanceOfBeingErnest Feb 21 '19 at 02:23
  • That's very helpful. Thank you. Unfortunately, I cannot find a suitable attribute such as "_markerstyle" or "_marker" as I can find for color. What's the attribute named that should be manipulated for changing the marker? It would also be nice to be able to change the marker pointwise. I know that you've created an issue on GH about this last year, suggesting a list of markers. Has this been implemented yet? – whiletrue Feb 21 '19 at 02:47
  • solved it, appreciate it @ImportanceOfBeingErnest. I conclude: there's a LOT of documentation work still to be done for matplotlib. I might chip in by PRing in the future. – whiletrue Feb 21 '19 at 07:38

1 Answers1

0

The solution to iteratively adding points to an animated 3D scatter plot with different markers and colors using the private matplotlib functions in my example goes as follows:

import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.markers as mmarkers
import matplotlib.cm as cm
import matplotlib.animation

colors = cm.tab10(np.linspace(0, 1, len(pos_gt)))


def update_graph(num):
    x_updated = np.concatenate([pos_gt.x[:num+1].tolist(), pos_pred.x[:num+1].tolist()])
    y_updated = np.concatenate([pos_gt.y[:num+1].tolist(), pos_pred.y[:num+1].tolist()])
    z_updated = np.concatenate([pos_gt.z[:num+1].tolist(), pos_pred.z[:num+1].tolist()])

    paths_gt = []
    paths_ped = []
    for i in range(num+1):
        marker_gt = mmarkers.MarkerStyle('o')
        marker_ped = mmarkers.MarkerStyle('x')
        path_gt = marker_gt.get_path().transformed(marker_gt.get_transform())
        path_ped = marker_ped.get_path().transformed(marker_ped.get_transform())
        paths_gt.append(path_gt)
        paths_ped.append(path_ped)

    graph._paths = np.concatenate([paths_gt, paths_ped])
    graph._facecolor3d = np.concatenate([colors[:num+1],colors[:num+1]])
    graph._edgecolor3d = np.concatenate([colors[:num+1],colors[:num+1]])
    graph._offsets3d = (x_updated, y_updated, z_updated)



fig = plt.figure(dpi=200)
ax = fig.add_subplot(111, projection='3d')
title = ax.set_title('plot title')


graph = ax.scatter([], [], [], s=70)
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(0, 1)
graph.set_alpha(1)

ani = matplotlib.animation.FuncAnimation(fig, update_graph, frames=9, interval=600, repeat_delay=5000, blit=False)

plt.show()
whiletrue
  • 10,500
  • 6
  • 27
  • 47