如何修复CSV数据绘制的3D天线辐射图连接不光滑问题
问题
从CSV文件加载天线辐射方向图数据,格式如下:
Theta Phi Dir 0 0.000 0.0 8.272 1 5.000 0.0 8.221 2 10.000 0.0 8.064 3 15.000 0.0 7.804 4 20.000 0.0 7.444 ... ... ... ... 2659 160.000 355.0 -13.240 2660 165.000 355.0 -12.330 2661 170.000 355.0 -11.460 2662 175.000 355.0 -10.870 2663 180.000 355.0 -10.670
Theta范围0°至180°,Phi范围0°至355°。运行以下Python代码绘制3D图后,出现数值间连接不光滑、曲面回退至(0,0,0)点的问题:
import pandas as pd import numpy as np from array import * import numpy as np import pandas as pd import plotly.graph_objects as go from plotly.offline import plot # Read data from CSV file df = pd.read_csv('output_file.csv') # reshaping data for plot theta1d = df['Theta'] theta1d = np.array(theta1d) theta1d_unique = np.unique(theta1d) angle_count_theta = len(theta1d_unique) phi1d = df['Phi'] phi1d = np.array(phi1d) phi1d_unique = np.unique(phi1d) angle_count_phi = len(phi1d_unique) theta2d = theta1d.reshape([angle_count_theta, angle_count_phi]) phi2d = phi1d.reshape([angle_count_theta, angle_count_phi]) dir1d = df['Dir'] dir1d = np.array(dir1d) R = np.empty((angle_count_theta, angle_count_phi)) row_count = 0 for j in range(angle_count_phi): for i in range(angle_count_theta): R[i,j] = dir1d[row_count * angle_count_theta + i] row_count += 1 THETA = np.deg2rad(theta2d) PHI = np.deg2rad(phi2d) THETA = THETA.reshape(R.shape[0],R.shape[1]) PHI = PHI.reshape(R.shape[0],R.shape[1]) # transformation of spherical data X = R * np.sin(THETA) * np.cos(PHI) Y = R * np.sin(THETA) * np.sin(PHI) Z = R * np.cos(THETA) min_X = np.min(X) max_X = np.max(X) min_Y = np.min(Y) max_Y = np.max(Y) layout = go.Layout(title="3D Radiation Pattern of 5G CW data", xaxis = dict(range=[min_X,max_X],), yaxis = dict(range=[min_Y,max_Y],)) fig = go.Figure(data=[go.Surface(x=X, y=Y, z=Z, surfacecolor=R, colorscale='mygbm', colorbar = dict(title = "Gain", thickness = 50, xpad = 500))], layout = layout) fig.update_layout(autosize = True, margin = dict(l = 50, r = 50, t = 250, b = 250)) plot(fig)
解决方案
问题根源分析
- 数据重塑错误:手动填充
R矩阵时索引计算逻辑有误,导致数据排列混乱,曲面连接错位。 - Phi角度不闭合:数据中Phi仅到355°,缺少360°(等价于0°)的重复数据,Plotly无法闭合曲面,出现回退原点的问题。
- 冗余代码干扰:重复导入库、无效的
reshape操作增加代码复杂度,容易引发逻辑错误。
修复步骤
1. 正确生成二维R矩阵
用Pandas的pivot方法直接映射(Theta, Phi)与Dir的对应关系,避免手动循环的索引错误:
# 替换原代码中手动填充R的部分 pivot_df = df.pivot(index='Theta', columns='Phi', values='Dir') R = pivot_df.values theta1d_unique = pivot_df.index.values phi1d_unique = pivot_df.columns.values THETA = np.deg2rad(theta1d_unique)[:, np.newaxis] # 转为列向量实现广播 PHI = np.deg2rad(phi1d_unique)[np.newaxis, :] # 转为行向量实现广播
2. 闭合Phi角度范围
复制Phi=0°的行并将Phi改为360°,让角度形成闭合环:
# 在读取CSV后添加此代码 phi_0_row = df[df['Phi'] == 0.0].copy() phi_0_row['Phi'] = 360.0 df = pd.concat([df, phi_0_row], ignore_index=True)
3. 优化绘图参数与代码结构
- 移除冗余导入语句,简化代码。
- 将原2D布局参数替换为3D场景的
scene配置,适配3D图的轴设置。 - 添加
contours参数提升曲面光滑度。
完整修复后代码
import pandas as pd import numpy as np import plotly.graph_objects as go from plotly.offline import plot # 读取数据并闭合Phi角度 df = pd.read_csv('output_file.csv') phi_0_row = df[df['Phi'] == 0.0].copy() phi_0_row['Phi'] = 360.0 df = pd.concat([df, phi_0_row], ignore_index=True) # 生成二维R矩阵 pivot_df = df.pivot(index='Theta', columns='Phi', values='Dir') R = pivot_df.values theta_rad = np.deg2rad(pivot_df.index.values)[:, np.newaxis] phi_rad = np.deg2rad(pivot_df.columns.values)[np.newaxis, :] # 球坐标转笛卡尔坐标 X = R * np.sin(theta_rad) * np.cos(phi_rad) Y = R * np.sin(theta_rad) * np.sin(phi_rad) Z = R * np.cos(theta_rad) # 3D场景布局设置 layout = go.Layout( title="3D Radiation Pattern of 5G CW data", scene=dict( xaxis_title='X', yaxis_title='Y', zaxis_title='Z', aspectmode='data' ), autosize=True, margin=dict(l=50, r=50, t=100, b=50) ) # 绘制光滑曲面 fig = go.Figure(data=[go.Surface( x=X, y=Y, z=Z, surfacecolor=R, colorscale='Viridis', colorbar=dict(title="Gain", thickness=50), contours=dict( z=dict(show=True, usecolormap=True, highlightcolor="#42f462", project_z=True) ) )], layout=layout) plot(fig)
额外光滑度优化
若数据点间距较大,可通过插值生成更密集的网格:
from scipy.interpolate import griddata # 生成高密度角度网格 theta_dense = np.linspace(0, 180, 72) phi_dense = np.linspace(0, 360, 72) theta_grid, phi_grid = np.meshgrid(theta_dense, phi_dense) # 三次插值获取平滑的Dir值 points = df[['Theta', 'Phi']].values values = df['Dir'].values R_dense = griddata(points, values, (theta_grid, phi_grid), method='cubic') # 后续用R_dense进行坐标转换和绘图即可
内容的提问来源于stack exchange,提问作者Chey
相关产品推荐
相关产品推荐

