0

I am studying an evolving system, whose states are recorded as floats in a list of lists. Each rectangle represents a number; the number falling within various ranges will be drawn in different colors, like a leveled map. I want to portrait many shot throughout the system's evolution, and

For sake of simplicity, here is a minimal example. Each entry in the list of lists is added to a uniformly random walk when move_one_step is called. The difficulty is updating the figure object and calling move_one_step alternatively, in the correct way.

#!/usr/bin/env python3

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation

def move_one_step(list_in):
   hold_list =list_in
   for i in list(range(LEN_BLOCK)):
      for j in list(range(LEN_BLOCK)):
         list_in[i][j] +=np.random.uniform(0,VMAX) # Uniform within 0 and `VMAX`.
   return hold_list

LEN_BLOCK =10
MAX_NUM_STEP =10
VMAX =4

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

list_sys =[ [0]*LEN_BLOCK for _ in list(range(LEN_BLOCK)) ]
hold_axes =plt.pcolormesh(list_sys, vmin=0, vmax=VMAX)
plt.colorbar()
fig =hold_axes.get_figure()

out_video_path ="./evolution.mp4"
DPI =100 # Dots per inch.
FPS =5 # `fps`: frame rate

writer =animation.FFMpegWriter(fps=FPS)
with writer.saving(fig, out_video_path, DPI):
   for i in range(MAX_NUM_STEP):
      list_sys =move_one_step(list_sys)
      hold_axes.set_array(list_sys)
      writer.grab_frame()

The interpretation fails, and the error messages are, excerpted here,

Traceback (most recent call last):
  File "./animation.py", line 42, in <module>
    writer.grab_frame()
  File "/usr/local/lib/python3.6/site-packages/matplotlib/animation.py", line 328, in grab_frame
    dpi=self.dpi, **savefig_kwargs)
  File "/usr/local/lib/python3.6/site-packages/matplotlib/figure.py", line 1573, in savefig
...
[I omitted the rest]
...
AttributeError: 'list' object has no attribute 'ndim'

The error is not obvious. I believe I failed to correspond the types of axes and figure objects, but I have poor understanding regarding them.

Main source of my idea: 2D grid data visualization in Python ; Animation example code

Excuse me for that I just copy and paste and applied much guesswork of my own....

Violapterin
  • 337
  • 2
  • 14

2 Answers2

1

You are right that "the error is not obvious". There seems to be a very special detail about set_array(), mentioned in 2 of the answers to this question. That is you must use a 1D array for set_array(). And that also depends on the shading setting. I'm not sure what you really expect, but this will solve the error and give a video for your specific case here:

     Change hold_axes.set_array(list_sys)
      to hold_axes.set_array(np.array(list_sys).ravel()).

Y. Luo
  • 5,622
  • 1
  • 18
  • 25
0

Actually I just discover that I have to use 1d (not 2d) numpy array (not list), a little after @Luo's answer. A couple of things I want to remark: plt.pcolormesh returns a QuadMesh; QuadMesh's method set_array receives 1d array, that will be portraied from left to right Thus, it seems to me highly misleading that pcolormesh "only" receives a 2d array! (There are several minor errors in my code, but I do not have time to prepare another correct minimal example. Suffice to say the fail to correspond to function call, just as pointed out, is the source of error. If you find my understanding incorrect, please correct me in comments.)

Reference: matplotlib.collections (search, in the page, the method you want to know about, to see its "prototype")

Violapterin
  • 337
  • 2
  • 14