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.
为简单起见,这是一个最小的例子。当调用move_one_step时,列表列表中的每个条目被添加到均匀随机游走中。难点在于更新图形对象并以正确的方式调用move_one_step。
#!/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
我的想法的主要来源:Python中的2D网格数据可视化;动画示例代码
Excuse me for that I just copy and paste and applied much guesswork of my own....
对不起,我只是复制并粘贴并应用了我自己的猜测....
2 个解决方案
#1
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:
你是对的,“错误并不明显”。似乎有一个关于set_array()的非常特殊的细节,在这个问题的2个答案中提到。那就是你必须为set_array()使用一维数组。这也取决于阴影设置。我不确定你真正期望的是什么,但是这将解决错误并为你的具体案例提供一个视频:
Change hold_axes.set_array(list_sys)
to hold_axes.set_array(np.array(list_sys).ravel())
.
将hold_axes.set_array(list_sys)更改为hold_axes.set_array(np.array(list_sys).ravel())。
#2
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.)
实际上我只是发现我必须使用1d(不是2d)numpy数组(不是列表),在@Lo的回答之后。我想说几件事:plt.pcolormesh返回一个QuadMesh; QuadMesh的方法set_array接收1d数组,将从左到右进行描绘。因此,在我看来,pcolormesh“仅”接收到2d数组时,我觉得极具误导性! (我的代码中有一些小错误,但是我没有时间准备另一个正确的最小例子。我只想说,如果指出,未能对应函数调用是错误的来源。如果你找到我的理解不正确,请在评论中纠正我。)
Reference: matplotlib.collections (search, in the page, the method you want to know about, to see its "prototype")
参考:matplotlib.collections(在页面中搜索你想知道的方法,看看它的“原型”)
#1
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:
你是对的,“错误并不明显”。似乎有一个关于set_array()的非常特殊的细节,在这个问题的2个答案中提到。那就是你必须为set_array()使用一维数组。这也取决于阴影设置。我不确定你真正期望的是什么,但是这将解决错误并为你的具体案例提供一个视频:
Change hold_axes.set_array(list_sys)
to hold_axes.set_array(np.array(list_sys).ravel())
.
将hold_axes.set_array(list_sys)更改为hold_axes.set_array(np.array(list_sys).ravel())。
#2
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.)
实际上我只是发现我必须使用1d(不是2d)numpy数组(不是列表),在@Lo的回答之后。我想说几件事:plt.pcolormesh返回一个QuadMesh; QuadMesh的方法set_array接收1d数组,将从左到右进行描绘。因此,在我看来,pcolormesh“仅”接收到2d数组时,我觉得极具误导性! (我的代码中有一些小错误,但是我没有时间准备另一个正确的最小例子。我只想说,如果指出,未能对应函数调用是错误的来源。如果你找到我的理解不正确,请在评论中纠正我。)
Reference: matplotlib.collections (search, in the page, the method you want to know about, to see its "prototype")
参考:matplotlib.collections(在页面中搜索你想知道的方法,看看它的“原型”)