如何在Plotly的同一图表中绘制两个Volume图?
在Plotly单图中添加两个Volume trace的解决方案
问题根源
你第二个go.Volume trace无法显示的核心原因是缺少value参数。Plotly的Volume组件依赖value字段定义三维空间中每个点的数值密度,以此生成等值面(即体积形态)。你当前只传入了x/y/z的线性序列,没有提供体数据支撑,所以无法渲染出椭球或气泡形状。而go.Scatter3D仅需坐标点就能绘制线条/标记,因此可以正常显示。
修复方案:生成椭球体的体数据
要绘制椭球形气泡,需先生成覆盖目标区域的三维网格,计算每个网格点是否在椭球范围内,将符合条件的点设为特定数值,再通过value参数传入Volume组件,配合isomin/isomax控制显示的等值面。
完整代码示例
import plotly.graph_objects as go import numpy as np # 示例常量(替换为你的实际值) H = 10 C = 5 LO = 3 tol_up = 0.2 tol_low = 0.1 # 初始化图表并添加第一个Volume trace(保留你原有的代码) fig = go.Figure() # 假设X/Y/Z/d是你已定义的体数据 fig.add_trace(go.Volume( x=X, y=Y, z=Z, value=d, opacity=0.15, isomax=0.9, isomin=0.3, surface_count=17, colorbar=dict(title='KDE Norm Value'), )) # 生成椭球体的三维网格 center = np.array([H, C, LO]) # 根据tol计算椭球三个轴的半轴长度 axes = np.array([H*tol_up, C*tol_up, LO*tol_up]) # 生成覆盖椭球范围的网格点 x_grid = np.linspace(center[0]-axes[0], center[0]+axes[0], 50) y_grid = np.linspace(center[1]-axes[1], center[1]+axes[1], 50) z_grid = np.linspace(center[2]-axes[2], center[2]+axes[2], 50) X_ellip, Y_ellip, Z_ellip = np.meshgrid(x_grid, y_grid, z_grid) # 计算每个点到椭球中心的归一化距离,判断是否在椭球内 norm_dist = ((X_ellip - center[0])/axes[0])**2 + ((Y_ellip - center[1])/axes[1])**2 + ((Z_ellip - center[2])/axes[2])**2 # 椭球内部的点value设为1,外部设为0 value_ellip = np.where(norm_dist <= 1, 1, 0) # 添加第二个Volume trace(椭球气泡) fig.add_trace(go.Volume( x=X_ellip.flatten(), y=Y_ellip.flatten(), z=Z_ellip.flatten(), value=value_ellip.flatten(), opacity=0.8, isomin=0.5, # 仅显示value>=0.5的区域,即椭球内部 isomax=1, surface_count=1, # 只显示外层表面,模拟气泡效果 colorscale=[[0, 'rgba(0,0,0,0)'], [1, 'rgba(255,0,0,0.8)']], # 透明到红色的渐变 showscale=False # 不显示单独色条 )) fig.show()
关键说明
- 用
meshgrid生成三维网格,确保覆盖整个椭球区域 - 通过椭球方程筛选内部点,生成
value数组作为体数据 - 设置
surface_count=1可让椭球仅显示外层表面,更贴近气泡视觉效果 - 调整
opacity和colorscale可优化气泡的透明度与颜色表现
内容的提问来源于stack exchange,提问作者Art
相关产品推荐
相关产品推荐

