1

I have a 2D plot placed on one of the walls of a 3D plot that doesn't seem to reflect any changes from set_data(), I would like to understand what I'm doing wrong here.

Here is a sample code showing the 3D plot with the 2D 'projection' plot in question. The output is shown here:

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

plt.rcParams['legend.fontsize'] = 10

fig = plt.figure()
ax = fig.gca(projection='3d')

# Test data for projection onto xz plane
t = linspace(0,10, num=20)
z = np.sin(t)

# Plot projection
projx, = ax.plot(np.linspace(-1,0, num=len(z)), z, 'r', zdir='y', zs=1)

# Labels and scaling
ax.set_xlabel('M_x')
ax.set_ylabel('M_y')
ax.set_zlabel('M_z')
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.set_zlim(-1, 1)

# Update projection data
projx.set_data([0],[0])

# See if actually updated data
print(projx.get_xdata())

# Draw and display window
plt.draw()
ax.legend()

plt.show()

I imagine that this line:

projx.set_data([0],[0])

would make the projection plot virtually empty. Instead, the sine wave remains.

Furthermore, the printout yields [0] as expected, so the set_data() call was successful, but for some reason the plot doesn't get drawn with the new data.

Shouldn't the set_data() changes be reflected when drawn afterwards?

A. Khan
  • 11
  • 2
  • 1
    So, the 2D projections don't update in the animation, and to get help, you decided to show us not the animation code? Please read [How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). As a sidenote, don't use `from pylab import *`. Two reasons: you should [not use pylab](https://matplotlib.org/stable/api/index.html?highlight=pylab#module-pylab), and you should not [import *](https://stackoverflow.com/questions/2386714/why-is-import-bad) – Mr. T Feb 16 '21 at 10:07
  • The animation stuff was mostly context. I want to understand why this simpler code isn't working the way it should or at least why I'm misunderstanding it (it emulates the first cycle of the animation code). I'll edit the question to fit that however, ty. – A. Khan Feb 16 '21 at 11:16
  • I see. I don't fully understand the reason - it seems mainly because matplotlib based Line3D objects on Line2D objects, so there arise some problems from making functions compatible as [discussed here](https://stackoverflow.com/a/37529811/8881141). If your 3D plot works, as you said - why don't you simply adapt this strategy with a constant array for y=1? – Mr. T Feb 16 '21 at 13:14
  • Thank you for the suggestion and the provided link, fixing one of the axes of a 3dplot with a constant array did the trick~ – A. Khan Feb 16 '21 at 19:53

1 Answers1

0

There is a way to update a Line3D object by directly setting its vertices. Not sure, if this might have any negative side effects, though.

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.gca(projection='3d')

# Test data for projection onto xz plane
t = np.linspace(0,10, num=20)
z = np.sin(t)

# Plot projections
projx, = ax.plot(np.linspace(-1,0, num=len(z)), z, 'r', zdir='y', zs=1, label="changed")
projy, = ax.plot(np.linspace(-1,0, num=len(z)), z, 'b', zdir='x', zs=-1, label="not changed")

# Labels and scaling
ax.set_xlabel('M_x')
ax.set_ylabel('M_y')
ax.set_zlabel('M_z')
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.set_zlim(-1, 1)

#update vertices of one Line3D object
projx._verts3d = [0, 0.2, 0.7], [1, 1, 1], [0.5, 0.2, 0.7]

ax.legend()
plt.show()

Sample output: enter image description here

However, since one cannot omit any of the x, y, and z arrays, there is no real advantage over plotting it as a 3D array with one array being a constant.

Mr. T
  • 11,960
  • 10
  • 32
  • 54