我有一组(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。例如,在第一步(帧= 0)期间,没有高程,因此,在“冷暖”比例下,图应为白色,但也应采用蓝色和红色。
欢迎任何建议。
预先感谢
答案 0 :(得分:0)
最后,我得到了解决方案(感谢@ImportanceOfBeingErnest提供指导)。
所需步骤为:
a)定义cmap
和normalize
变量以创建“全局颜色图”
b)标准化每一帧的每个高度(Z)值,并将列表存储在数据帧的额外插槽中。
c)在update_graph(num)
内部,使用scat.set_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()