且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

重绘后Matplotlib 3D散布颜色丢失

更新时间:2023-02-05 18:42:38

目前尚不清楚为什么会发生这种情况,这肯定是一个错误.在这里,我提供了一种获取所需结果的技巧,尽管它并非像人们想要的那样自动实现.

It's not clear why this is happening, and it certainly is a bug. Here I provide a hack to get the result you want, though it is not as automatic as one would want.

由于某些原因,表示散点的Patch3DCollection在第一次渲染后不会更新.此更新是必不可少的,因为它是为每个集合补丁设置唯一颜色的地方.要强制它重新初始化,可以在Patch3DCollection上使用changed方法(实际上是ScalarMappable方法),这只是记录了发生的更改.绘制图形时,它将检查是否发生了更新,然后重新定义颜色.如果没有,则跳过此过程.

For some reason, the Patch3DCollection representing the scatter points is not updated after the first rendering. This update is essential, because it is where unique colors are set for each collection patch. To force it to reinitialize, you can use the changed method on the Patch3DCollection (really a ScalarMappable method), and this just documents that a change happend. When the figure is drawn, it checks if an update happened, and then it redefines the colors. If it didn't, this process is skipped.

要强制此更新自动发生,请在每个绘制"事件中执行此操作.为此,必须使用canvasmpl_connect 注册方法.方法(请参阅链接的教程).

To force this update to occur automatically, one would like to do this on every 'draw' event. To do this, one must register a method using the canvas's mpl_connect method (see linked tutorial).

此示例显示了两次保存图形如何保留颜色映射的方法,但是如果取消注释plt.show()行,它仍将起作用(例如,旋转).

This example shows how saving the figure twice preserves the color mapping, but if you uncomment the plt.show() line, it will still work (on rotation for example).

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

# Create Map
cm = plt.get_cmap("RdYlGn")

# added a seed so consistant plotting of points
np.random.seed(101)
x = np.random.rand(30)
y = np.random.rand(30)
z = np.random.rand(30)

col = np.arange(30)

fig = plt.figure()
#ax = fig.add_subplot(111)
#scatCollection = ax.scatter(x,y,
ax3D = fig.add_subplot(111, projection='3d')
# keep track of the Patch3DCollection:
scatCollection = ax3D.scatter(x, y, z, s=30, 
                            c=col, 
                            marker='o',
                            cmap=cm
                            )
def forceUpdate(event):
    global scatCollection
    scatCollection.changed()

fig.canvas.mpl_connect('draw_event',forceUpdate)

#plt.show()

plt.savefig('image1.png')

plt.savefig('image2.png')

理想情况下,不需要这样做,并且应该使用其他方法访问全局scatCollection(我正在努力做到这一点).但这暂时有效...

Ideally it should not be required to do this, and the global scatCollection should be accessed using other methods (I'm working on doing this). But this works for now...