Tom
Tom

Reputation: 55

Value error: Argument Z must be 2-dimensional

I have written a script, using coordinate values from a text file to move a sphere around in space.

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

df = pd.read_csv('/path/to/text/file', sep=" ", header=None)

fig = plt.figure(facecolor='black')
ax = plt.axes(projection = "3d")

u = np.linspace(0, 2*np.pi, 100)
v = np.linspace(0, np.pi, 100)
r = 4

ax.set_xlim(0, 60)
ax.set_ylim(0, 60)
ax.set_zlim(0, 60)

x0 = r * np.outer(np.cos(u), np.sin(v)) + df[1][0]
y0 = r * np.outer(np.sin(u), np.sin(v)) + df[2][0]
z0 = r * np.outer(np.ones(np.size(u)), np.cos(v)) + df[3][0]

surface_color = "tab:blue"

def init():
    ax.plot_surface(x0, y0, z0, color=surface_color)
    return fig,

def animate(i):
    # remove previous collections
    ax.collections.clear()
    x = df[1][i]
    y = df[2][i]
    z = df[3][i]
    # add the new sphere
    ax.plot_surface(x, y, z, color=surface_color)
    return fig,

ani = animation. FuncAnimation(fig, animate, init_func = init, frames = 500, interval = 2)


plt.show()

The code produces the error "Value error: Argument Z must be 2-dimensional" and I'm not entirely sure why or how to solve this.

Full error message:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 1921, in __call__
    return self.func(*args)
  File "C:\Users\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 839, in callit
    func(*args)
  File "C:\Users\Downloads\pythonProject1\venv\lib\site-packages\matplotlib\backends\_backend_tk.py", line 141, in _on_timer
    super()._on_timer()
  File "C:\Users\Downloads\pythonProject1\venv\lib\site-packages\matplotlib\backend_bases.py", line 1198, in _on_timer
    ret = func(*args, **kwargs)
  File "C:\Users\Downloads\pythonProject1\venv\lib\site-packages\matplotlib\animation.py", line 1406, in _step
    still_going = super()._step(*args)
  File "C:\Users\Downloads\pythonProject1\venv\lib\site-packages\matplotlib\animation.py", line 1105, in _step
    self._draw_next_frame(framedata, self._blit)
  File "C:\Users\Downloads\pythonProject1\venv\lib\site-packages\matplotlib\animation.py", line 1124, in _draw_next_frame
    self._draw_frame(framedata)
  File "C:\Users\Downloads\pythonProject1\venv\lib\site-packages\matplotlib\animation.py", line 1718, in _draw_frame
    self._drawn_artists = self._func(framedata, *self._args)
  File "C:\Users\Downloads\pythonProject1\main.py", line 38, in animate
    ax.plot_surface(x, y, z, color=surface_color)
  File "C:\Users\Downloads\pythonProject1\venv\lib\site-packages\matplotlib\_api\deprecation.py", line 415, in wrapper
    return func(*inner_args, **inner_kwargs)
  File "C:\Users\Downloads\pythonProject1\venv\lib\site-packages\mpl_toolkits\mplot3d\axes3d.py", line 1581, in plot_surface
    raise ValueError("Argument Z must be 2-dimensional.")
ValueError: Argument Z must be 2-dimensional.

This is exactly what it says when I run the code

Upvotes: 0

Views: 315

Answers (1)

Giovanni Tardini
Giovanni Tardini

Reputation: 568

Edited I made a better x_grid, y_grid, not using the original x, y, but rather a regular grid between their min and max values. FIrst, x and y might have a huge dimension, making plotting very slow and heavy. Second, they are probably sparse data, with no regular distribution.

You probably need to define the data on a grid. Having X(n), Y(n), Z(n) for 3D plots is not directly usable. You need something like:

from scipy.interpolate import griddata
import numpy as np

n_cells = 100
xg = np.linspace(x.min(), x.max(), n_cells)
yg = np.linspace(y.min(), y.max(), n_cells)
x_grid, y_grid = np.meshgrid(xg, yg)
z2d = griddata((x, y), z, (x_grid, y_grid), method='linear')
ax.plot_surface(x_grid, y_grid, z2d, color=surface_color)

I cannot test it directly because I do not quite know what your x, y, z are, but I have seen that problem before and I solved it this way.

Upvotes: 1

Related Questions