为了账号安全,请及时绑定邮箱和手机立即绑定

Python - 绘制天线辐射图

Python - 绘制天线辐射图

慕姐8265434 2021-11-16 14:44:48
这是我找到并稍微修改的代码。如何从原点缩放颜色并为可视化设置从原点开始的轴?我试图找到信息,但其中大部分是针对二维图的。在这里,我已经添加了两个阵列以theta和phi以45度的间隔和表示信号的功率的随机数的阵列。该图有效,但信号和间隔不太正确。我的目标是从原点添加轴并从原点缩放颜色。import pandas as pdimport numpy as npimport scipy as sciimport matplotlib.pyplot as pltimport mpl_toolkits.mplot3d.axes3d as Axes3Dfrom matplotlib import cm, colorsfrom array import *import random#theta vals_theta = array('i',[0,0,0,0,0,0,0,0,0,45,45,45,45,45,45,45,45,45,90,90,90,                         90,90,90,90,90,90,135,135,135,135,135,135,135,135,135,                        180,180,180,180,180,180,180,180,180])#phivals_phi = array('i',[0,45,90,135,180,225,270,315,360,                      0,45,90,135,180,225,270,315,360,                      0,45,90,135,180,225,270,315,360,                      0,45,90,135,180,225,270,315,360,                      0,45,90,135,180,225,270,315,360])#random numbers simulating the power datavals_power = np.random.uniform(low=-7.2E-21, high=7.2E-21, size=(45,))theta1d = vals_thetatheta1d = np.array(theta1d);theta2d = theta1d.reshape([5,9])phi1d = vals_phiphi1d = np.array(phi1d);phi2d = phi1d.reshape([5,9])power1d = vals_powerpower1d = np.array(power1d);power2d = power1d.reshape([5,9])THETA = np.deg2rad(theta2d)PHI = np.deg2rad(phi2d)R = power2dRmax = np.max(R)X = R * np.sin(THETA) * np.cos(PHI)Y = R * np.sin(THETA) * np.sin(PHI)Z = R * np.cos(THETA)fig = plt.figure()ax = fig.add_subplot(1,1,1, projection='3d')ax.grid(True)ax.axis('on')ax.set_xticks([])ax.set_yticks([])ax.set_zticks([])N = R / Rmaxax.plot_surface(    X, Y, Z, rstride=1, cstride=1, cmap=plt.get_cmap('jet'),    linewidth=0, antialiased=False, alpha=0.5, zorder = 0.5)ax.set_title('Spherical 3D Plot', fontsize=20)m = cm.ScalarMappable(cmap=cm.jet)m.set_array(R)ax.set_xlabel('X')ax.set_ylabel('Y')ax.set_zlabel('Z')m = cm.ScalarMappable(cmap=cm.jet)m.set_array(R) fig.colorbar(m, shrink=0.8);ax.view_init(azim=300, elev = 30)试图获得与此近似的结果
查看完整描述

2 回答

?
撒科打诨

TA贡献1934条经验 获得超2个赞

这是建立在 Andrea 的出色答案的基础上的,其中添加了一些对点之间可能具有相当宽间距的真实世界数据有所帮助的补充。当我第一次以 45 度间距绘制一些东西时,它看起来像这样:

//img1.sycdn.imooc.com//619353b00001707001900158.jpg

有两个明显的问题:

  1. 这些面非常大,只有一种颜色,尽管它们跨越了很宽的数值范围。

  2. 形状关于原点对称,但面的颜色不对称。

可以通过对数据进行线性插值来改进问题 1,以便将每个面分为多个可以具有不同颜色的部分。

问题 2 发生的原因是面部颜色的分配方式。想象一下 2D 平面上的 3x3 点网格,每个点都有一个值。当您绘制曲面时,将只有 2x2 个面,因此最后一行和最后一列的值被丢弃,每个面的颜色仅由面的一个角决定。我们真正想要的是每个面中心的值。我们可以通过取四个角值的平均值并使用它来分配颜色来估计这一点。

在计算上,这最终类似于问题 1 的插值,因此我对两者使用了相同的函数“interp_array”。我不是一个 Python 程序员,所以可能有一种更有效的方法来做到这一点,但它可以完成工作。

这是修复了问题 2 但没有插值的图。对称性是固定的,但只使用了 2 种颜色,因为面与原点等距。

//img1.sycdn.imooc.com//619353bb000142be01850165.jpg

这是在点之间进行 8x 插值的最终图。现在它更接近于您在商业天线测量软件中看到的那种连续彩色图。

//img1.sycdn.imooc.com//619353c80001a76604660386.jpg

import numpy as np

import matplotlib.pyplot as plt

import mpl_toolkits.mplot3d.axes3d as Axes3D

from matplotlib import cm, colors


def interp_array(N1):  # add interpolated rows and columns to array

    N2 = np.empty([int(N1.shape[0]), int(2*N1.shape[1] - 1)])  # insert interpolated columns

    N2[:, 0] = N1[:, 0]  # original column

    for k in range(N1.shape[1] - 1):  # loop through columns

        N2[:, 2*k+1] = np.mean(N1[:, [k, k + 1]], axis=1)  # interpolated column

        N2[:, 2*k+2] = N1[:, k+1]  # original column

    N3 = np.empty([int(2*N2.shape[0]-1), int(N2.shape[1])])  # insert interpolated columns

    N3[0] = N2[0]  # original row

    for k in range(N2.shape[0] - 1):  # loop through rows

        N3[2*k+1] = np.mean(N2[[k, k + 1]], axis=0)  # interpolated row

        N3[2*k+2] = N2[k+1]  # original row

    return N3



vals_theta = np.arange(0,181,45)

vals_phi = np.arange(0,361,45)


vals_phi, vals_theta = np.meshgrid(vals_phi, vals_theta)


THETA = np.deg2rad(vals_theta)

PHI = np.deg2rad(vals_phi)


# simulate the power data

R = abs(np.cos(PHI)*np.sin(THETA))  # 2 lobes (front and back)


interp_factor = 3  # 0 = no interpolation, 1 = 2x the points, 2 = 4x the points, 3 = 8x, etc


X = R * np.sin(THETA) * np.cos(PHI)

Y = R * np.sin(THETA) * np.sin(PHI)

Z = R * np.cos(THETA)


for counter in range(interp_factor):  # Interpolate between points to increase number of faces

    X = interp_array(X)

    Y = interp_array(Y)

    Z = interp_array(Z)


fig = plt.figure()


ax = fig.add_subplot(1,1,1, projection='3d')

ax.grid(True)

ax.axis('on')

ax.set_xticks([])

ax.set_yticks([])

ax.set_zticks([])


N = np.sqrt(X**2 + Y**2 + Z**2)

Rmax = np.max(N)

N = N/Rmax


axes_length = 1.5

ax.plot([0, axes_length*Rmax], [0, 0], [0, 0], linewidth=2, color='red')

ax.plot([0, 0], [0, axes_length*Rmax], [0, 0], linewidth=2, color='green')

ax.plot([0, 0], [0, 0], [0, axes_length*Rmax], linewidth=2, color='blue')


# Find middle points between values for face colours

N = interp_array(N)[1::2,1::2]


mycol = cm.jet(N)


surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=mycol, linewidth=0.5, antialiased=True, shade=False)  # , alpha=0.5, zorder = 0.5)


ax.set_xlim([-axes_length*Rmax, axes_length*Rmax])

ax.set_ylim([-axes_length*Rmax, axes_length*Rmax])

ax.set_zlim([-axes_length*Rmax, axes_length*Rmax])


m = cm.ScalarMappable(cmap=cm.jet)

m.set_array(R)

ax.set_xlabel('X')

ax.set_ylabel('Y')

ax.set_zlabel('Z')


fig.colorbar(m, shrink=0.8)

ax.view_init(azim=300, elev=30)


plt.show()


查看完整回答
反对 回复 2021-11-16
?
智慧大石

TA贡献1946条经验 获得超3个赞

您可以添加单位长度的轴线:


ax.plot([0, 1], [0, 0], [0, 0], linewidth=2, color = 'red')

ax.plot([0, 0], [0, 1], [0, 0], linewidth=2, color = 'green')

ax.plot([0, 0], [0, 0], [0, 1], linewidth=2, color = 'blue')

关于表面的颜色,您需要定义一个表达式来表示距原点的距离,然后使用此表达式创建您的颜色图并将其传递给facecolors参数ax.plot_surfaceas 此处:


dist = np.sqrt(X**2 + Y**2 + Z**2)

dist_max = np.max(dist)

my_col = cm.jet(dist/dist_max)


surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=my_col, linewidth=0, antialiased=False)

完整代码:


from matplotlib import cm

import matplotlib.pyplot as plt

import numpy as np


fig = plt.figure()

ax = fig.gca(projection='3d')

X = np.arange(-5, 5, 0.25)

Y = np.arange(-5, 5, 0.25)

X, Y = np.meshgrid(X, Y)

R = np.sqrt(X**2 + Y**2)

Z = 8*np.sin(R)

dist = np.sqrt(X**2 + Y**2 + Z**2)

dist_max = np.max(dist)

my_col = cm.jet(dist/dist_max)


axes_length = 1.5

ax.plot([0, axes_length*dist_max], [0, 0], [0, 0], linewidth=2, color = 'red')

ax.plot([0, 0], [0, axes_length*dist_max], [0, 0], linewidth=2, color = 'green')

ax.plot([0, 0], [0, 0], [0, axes_length*dist_max], linewidth=2, color = 'blue')


surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=my_col,

        linewidth=0, antialiased=False)


ax.set_xlim([-axes_length*dist_max, axes_length*dist_max])

ax.set_ylim([-axes_length*dist_max, axes_length*dist_max])

ax.set_zlim([-axes_length*dist_max, axes_length*dist_max])


plt.show()

这给了我这个结果:

//img1.sycdn.imooc.com//619353dc0001ee6406080442.jpg

如您所见,表面的颜色从原点附近的蓝色变为远离原点的红色。将此代码应用于您的数据应该不难。


查看完整回答
反对 回复 2021-11-16
  • 2 回答
  • 0 关注
  • 558 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信