使用plotly.graph_objects模块Scatter3D和scatter3d.Line我无法让线条颜色落在定义色标的范围内。
我尝试了以下代码,通过将相应的“go.Scatter3D”附加到作为数据提供给“go.FigureWidget”的数据列表中,将点绘制为标记和线条
import numpy as np
import plotly.graph_objects as go
# define function
def get_3D_plot_stack(x,y,z,connections,elongation_values):
data_list = [] #initializing empty list
### Points, gathering data and appending to data_list
for i,(xi,yi,zi) in enumerate(zip(x,y,z)): # looping through each point_list
data_list.append(go.Scatter3d(x=[xi], y=[yi], z=[zi],
mode='markers',
marker=dict(color='black',size=2),
showlegend= False))
### Lines, gathering data and appending to data_list
for i,(conn,elongation_i) in enumerate(zip(connections,elongation_values)):
xi_conn = [x[conn[0]], x[conn[1]]]
yi_conn = [y[conn[0]], y[conn[1]]]
zi_conn = [z[conn[0]], z[conn[1]]]
data_list.append(go.Scatter3d(
x=xi_conn, y=yi_conn, z=zi_conn,
mode='lines',
line=go.scatter3d.Line(
width = 4,
color=elongation_i,
colorscale='Viridis',
showscale=True, #set to TRUE
),
showlegend=False
))
### Create figure
fig = go.FigureWidget(data=data_list)
fig.show()
return()
x,y,z = np.random.random_sample((3,10)) # random points
connections = np.array([[0,1],[9,2],[2,3],[5,7],[6,8],[2,8],[1,2],[4,5]]) # line connections
elongation_values = np.random.random_sample((len(connections))) # random colors
get_3D_plot_stack(x,y,z,connections,elongation_values)
通过绘制一次所有线条的颜色条值进行了改进。但这并不能解决问题(使用此 GitHub 问题中找到的旧解决方法实现颜色栏也没有解决:https://github.com/plotly/plotly.py/issues/1085)
import numpy as np
import plotly.graph_objects as go
def get_3D_plot_stack(x,y,z,connections,elongation_values):
data_list = [] #initializing an empty list
### Points, gathering data and appending to data_list
for i,(xi,yi,zi) in enumerate(zip(x,y,z)): # looping through each point_list
data_list.append(go.Scatter3d(x=[xi], y=[yi], z=[zi],
mode='markers',
marker=dict(color='black',size=2),
showlegend= False))
### Lines, gathering data and appending to data_list
x_conn, y_conn, z_conn = np.empty((len(connections),2)), np.empty((len(connections),2)), np.empty((len(connections),2))
for i,(conn,elongation_i) in enumerate(zip(connections,elongation_values)):
xi_conn = [x[conn[0]], x[conn[1]]]
yi_conn = [y[conn[0]], y[conn[1]]]
zi_conn = [z[conn[0]], z[conn[1]]]
# storing data
x_conn[i], y_conn[i], z_conn[i] = xi_conn, yi_conn, zi_conn
data_list.append(go.Scatter3d(
x=xi_conn, y=yi_conn, z=zi_conn,
mode='lines',
line=go.scatter3d.Line(
width = 4,
color=elongation_i,
colorscale='Viridis',
showscale=False, #set to FALSE
),
showlegend=False
))
## getting the colorbar once
line_trace_all = go.Scatter3d( x=x_conn, y=y_conn, z=z_conn,
mode='lines',
line=go.scatter3d.Line(
color=elongation_values,
colorscale='Viridis',
showscale=True),
showlegend=False)
data_list.append(line_trace_all)
### Create figure
fig = go.FigureWidget(data=data_list)
fig.show()
return()
x,y,z = np.random.random_sample((3,10))
connections = np.array([[0,1],[9,2],[2,3],[5,7],[6,8],[2,8],[1,2],[4,5]]) #random
elongation_values = np.random.random_sample((len(connections)))
get_3D_plot_stack(x,y,z,connections,elongation_values)
下面的代码试图使用
matplotlib
来完成此任务。我的理解是 elongation_values
代表要连接的点的索引;您希望颜色由 elongation_values
定义;并且颜色条应缩放到elongation_values
的范围。
代码首先绘制散点。然后它迭代
connections
,每次绘制一条连接由 connections
定义的两个点的线。
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
#Random points
np.random.seed(8)
rand_pts = np.random.random_sample(size=(10, 3))
x_vals, y_vals, z_vals = rand_pts.T
#Lines connecting some points, and their colours
connections = np.array([[0, 1], [9, 2], [2, 3], [5, 7], [6, 8], [2, 8], [1, 2], [4, 5]]) # line connections
elongation_values = np.random.random_sample((len(connections))) # random colors
fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(projection='3d')
colourmap = matplotlib.cm.viridis
#Plot points
ax.scatter3D(x_vals, y_vals, z_vals, c='k', s=60, alpha=1)
#For each entry in 'connections', plot a line joining two points
for (conn0, conn1), elong_val in zip(connections, elongation_values):
x0, y0, z0 = rand_pts[conn0]
x1, y1, z1 = rand_pts[conn1]
ax.plot3D([x0, x1], [y0, y1], [z0, z1], c=colourmap(elong_val), linewidth=3.2)
#Make a new axis for the colourbar, positioning it at the right
ax_pos = ax.get_position()
cax = fig.add_axes([ax_pos.x0 + ax_pos.width * 1.1, ax_pos.y0 + 0.1, ax_pos.width / 15, ax_pos.height * 0.7])
#Add colorbar
# First define a scale where the min elongation is mapped to 0, and
# the max elongation is mapped to 1
colour_scaling = matplotlib.colors.Normalize(vmin=elongation_values.min(),
vmax=elongation_values.max())
fig.colorbar(matplotlib.cm.ScalarMappable(norm=colour_scaling, cmap=colourmap), cax=cax)