Python 如何将colormap作为散点图的迭代器

Python 如何将colormap作为散点图的迭代器,python,matplotlib,iterator,colormap,Python,Matplotlib,Iterator,Colormap,我有一组(xyz)点,我正在散点图中绘制它们。 这组点随时间而变化,因此,使用迭代器更新每个步骤。 目前,我能够提取绘图的最大高程(在Z方向),以便定义最大/最小值并规范化颜色贴图。 但是,更新步骤后,我不知道如何将绘图的高程值链接到颜色贴图(以前定义的) 现在,代码在不更新颜色的情况下工作。 我试图将变量colormap包含为迭代器,但找不到执行此任务的命令 #Python moduels import numpy as np import matplotlib.pyplot as plt f

我有一组(xyz)点,我正在散点图中绘制它们。 这组点随时间而变化,因此,使用迭代器更新每个步骤。 目前,我能够提取绘图的最大高程(在Z方向),以便定义最大/最小值并规范化颜色贴图。 但是,更新步骤后,我不知道如何将绘图的高程值链接到颜色贴图(以前定义的)

现在,代码在不更新颜色的情况下工作。 我试图将变量colormap包含为迭代器,但找不到执行此任务的命令

#Python moduels
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
import matplotlib.animation
import pandas as pd

###############################################################################
#Generate data
###############################################################################

np.random.seed(10) #To obtain the same result

n_radii  = 8
n_angles = 120

# Make radii and angles spaces (radius r=0 omitted to eliminate duplication).
radii = np.linspace(0.125, 1.0, n_radii)
angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)

# Repeat all angles for each radius.
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)

# Convert polar (radii, angles) coords to cartesian (x, y) coords.
# (0, 0) is manually added at this stage,  so there will be no duplicate
# points in the (x, y) plane.
x = np.append(0, (radii*np.cos(angles)).flatten())
y = np.append(0, (radii*np.sin(angles)).flatten())

rows = len(x)
dim = 3
samples = 10

data = np.zeros((rows,dim,samples)) # (20 xyz) points stored in 10 sets 

for i in range(samples):
    data[:,0,i] = x
    data[:,1,i] = y
    # Compute z to make the pringle surface.
    data[:,2,i] = np.sin(-i*x*y)

index = np.arange(0,samples,1)

Frame = np.array([np.ones(rows)*index[i] for i in range(samples)]).flatten()

a = np.zeros((len(Frame),3))

for i in range(samples):
    a[i*rows:(i+1)*rows,0] = data[:,0,i]
    a[i*rows:(i+1)*rows,1] = data[:,1,i]
    a[i*rows:(i+1)*rows,2] = data[:,2,i]

df = pd.DataFrame({"Frame": Frame ,"x" : a[:,0], "y" : a[:,1], "z" : a[:,2]})

##############################################################################
#SCATTER PLOT
################################################################################

#Function to update my scatter plot
def update_graph(num):

    data = df[df['Frame'] == index[num]]
    graph._offsets3d = (data.x, data.y, data.z)
    title.set_text(r'How to update the color map for each plot based on the value of, Frame={}'.format(round(index[num],3)))

#Limits of Elevation (U3) in data
print('U3_min',min(a[:,2]))
print('U3_max',max(a[:,2]))

#Define figure
fig = plt.figure(figsize=(10, 8), dpi=200)

title = plt.suptitle(r'How to update the color map for each plot based on the value of, Frame={}'.format(round(index[0],3), fontsize=16))

# cmap will generate a tuple of RGBA values for a given number in the range 0.0 to 1.0 
# (also 0 to 255 - not used in this example).
# To map our z values cleanly to this range, we create a Normalize object.
cmap      = matplotlib.cm.get_cmap('coolwarm')
normalize = matplotlib.colors.Normalize(vmin=min(data[:,2,-1]), vmax=max(data[:,2,-1]))
colors = [cmap(normalize(value)) for value in data[:,2,-1]]

ax1 = fig.add_subplot(111, projection='3d')
ax1.view_init(45,30)
ax1.set_xlabel('X (mm)')
ax1.set_ylabel('Y (mm)')
ax1.set_zlabel('Z Elevation (mm)')

data=df[df['Frame']==1]
graph = ax1.scatter(data.x, data.y, data.z, color=colors)

## Optionally add a colorbar
cax, _ = matplotlib.colorbar.make_axes(ax1, shrink=0.5)
cbar   = matplotlib.colorbar.ColorbarBase(cax, cmap=cmap, norm=normalize)

#Animation
ani = matplotlib.animation.FuncAnimation(fig, update_graph, samples, 
                               interval=40, blit=False)
plt.show()
在所附文件中,为问题的最后一帧定义了颜色映射,其中U3max=1,U3min=-1。例如,在第一步(frame=0)中,没有高程,因此,在“coolwarm”比例中,绘图应为白色,但也采用蓝色和红色的值

欢迎提出任何建议


提前感谢

最后,我得到了解决方案(感谢@ImportanceOfBeingErnest的指导)。 所需的步骤是: a) 定义
cmap
,并
规范化
变量以创建“全局颜色映射” b) 规范化每个帧的每个高度(Z)值,并将列表存储在dataframe的额外插槽中。 c) 在
update\u graph(num)
的内部,使用
scat.set\u array(array)
传递先前的高度标准化值。 d) 使用
c
参数定义图形。 附加您可以看到最终的代码

#Python modules
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
import matplotlib.animation
import pandas as pd
from mpl_toolkits.mplot3d import Axes3D

###############################################################################
#Generate data
###############################################################################

np.random.seed(10) #To obtain the same result

n_radii  = 8
n_angles = 120

# Make radii and angles spaces (radius r=0 omitted to eliminate duplication).
radii = np.linspace(0.125, 1.0, n_radii)
angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)

# Repeat all angles for each radius.
angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)

# Convert polar (radii, angles) coords to cartesian (x, y) coords.
# (0, 0) is manually added at this stage,  so there will be no duplicate
# points in the (x, y) plane.
x = np.append(0, (radii*np.cos(angles)).flatten())
y = np.append(0, (radii*np.sin(angles)).flatten())

rows = len(x)
dim = 3
samples = 5

data = np.zeros((rows,dim,samples)) # (20 xyz) points stored in 10 sets 

for i in range(samples):
    data[:,0,i] = x
    data[:,1,i] = y
    # Compute z to make the pringle surface.
    data[:,2,i] = np.sin(-i*x*y)

index = np.arange(0,samples,1)

Frame = np.array([np.ones(rows)*index[i] for i in range(samples)]).flatten()

a = np.zeros((len(Frame),4))

for i in range(samples):
    a[i*rows:(i+1)*rows,0] = data[:,0,i]
    a[i*rows:(i+1)*rows,1] = data[:,1,i]
    a[i*rows:(i+1)*rows,2] = data[:,2,i]

# cmap will generate a tuple of RGBA values for a given number in the range 0.0 to 1.0 
# (also 0 to 255 - not used in this example).
# To map our z values cleanly to this range, we create a Normalize object.
cmap      = matplotlib.cm.get_cmap('coolwarm') #'viridis')#
normalize = matplotlib.colors.Normalize(vmin=min(a[:,2]), vmax=max(a[:,2]))

colors    = [cmap(normalize(value)) for value in data[:,2,-1]]
color_list= []

for i in range(samples):
   color_temp = [normalize(value) for value in data[:,2,i]]
   color_list = color_list + color_temp 

df = pd.DataFrame({"Frame": Frame ,"x" : a[:,0], "y" : a[:,1], "z" : a[:,2], "colors":color_list})

##############################################################################
#SCATTER PLOT
################################################################################

#Function to update my scatter plot
def update_graph(num):

    data_plot = df[df['Frame'] == index[num]]
    graph._offsets3d = (data_plot.x, data_plot.y, data_plot.z) #Update data
    graph.set_array(data_plot.colors) #Update colors

    title.set_text(r'How to update the color map for each plot based on the value of, Frame={}'.format(round(index[num],3)))

    return

#Limits of Elevation (U3) in data
print('U3_min',min(a[:,2]))
print('U3_max',max(a[:,2]))

#Define figure
fig = plt.figure(figsize=(10, 8), dpi=200)

title = plt.suptitle(r'How to update the color map for each plot based on the value of, Frame={}'.format(round(index[0],3), fontsize=16))

ax1 = fig.add_subplot(111, projection='3d')
ax1.view_init(45,30)
ax1.set_xlabel('X (mm)')
ax1.set_ylabel('Y (mm)')
ax1.set_zlabel('Z Elevation (mm)')

data_plot = df[df['Frame']==1]
graph     = ax1.scatter(data_plot.x, data_plot.y, data_plot.z, cmap=cmap, c=data_plot.colors, edgecolors='none')

## Optionally add a colorbar
cax, _ = matplotlib.colorbar.make_axes(ax1, shrink=0.5)
cbar   = matplotlib.colorbar.ColorbarBase(cax, cmap=cmap, norm=normalize, extend='both')

#Animation
ani = matplotlib.animation.FuncAnimation(fig, update_graph, frames = range(samples),) 


plt.show()

颜色映射是恒定的。这是否理想?与现在相比,我真的很难理解您最终想要实现什么,尤其是因为代码没有尝试更改代码中的颜色animation@ImportanceOfBeingErnest. 谢谢你的评论。为了澄清我的帖子,需要定义一个恒定的“全局”颜色映射(完成),以便用作每个帧的参考。现在,问题是:a)我不知道如何更新“本地”颜色映射(参考每个帧)或b)如何将本地颜色映射链接到全局颜色映射。这意味着我知道U3max/min值(在本例中为1和-1),现在,局部最大值/最小值总是有蓝色/红色,而它们与全局最大值/最小值不对应。我仍然不理解这个问题。你读了吗?@ImportanceOfBeingErnest。谢谢你指出参考资料。现在,我知道使用的方法是
scat.set\u array(array)
。但是,我尝试将其包含在代码中,但在需要将数据规范化到全局颜色映射之前。我试图在
update\u graph(num,graph,cmap,normalize)函数中为data.z中的值包含一行类似于
color\u update=[cmap(normalize(value))
的内容,但它不起作用。有什么建议吗?主要的区别是您自己指定颜色,而您更愿意使用
c
参数并直接提供值,如链接答案所示。