目录
最近正在学习通信仿真,可以利用Python更加直观地感受信号的变化。
准备工作
Python通过其丰富的库和框架为信号处理提供了强大的支持,使用python进行信号处理需要三个包:Numpy , Matplotlib , Scipy
在命令行中:
使用以下命令安装Numpy,主要用于数据的产生与组织
pip install numpy
使用以下命令安装Matplotlib,主要使用其中的pyplot模块进行信号的可视化
pip install matplotlib
使用以下命令安装Scipy,主要利用其signal模块进行信号处理和各种变换
pip install scipy
作出第一个信号
先拿最简单的正弦信号练练手:
作出下面正弦信号的图像
程序代码如下:
#导入所需的包
import numpy as np
import matplotlib.pyplot as plt
f=10 #频率定为10Hz
t=np.linspace(0 , 1 , 500) #范围从0-1,等间隔取500个点
y=np.sin( 2*np.pi*f * t) #此处的y也是500个点,与t的值一一对应
plt.figure(figsize=(10,4)) #创建一张10×4大小的图像
plt.plot(t,y) #作出曲线
plt.show() #注意:一定要有这行代码,否则图像不会显示!
得到信号图像:
下面简单解释一下代码:
t=np.linspace(0 , 1 , 500)
np.linspace(start,stop,num) 用于创建均匀间隔的一维序列,可以传入三个参数:依次为起始值,终止值,点的数量,得到的序列默认是包含起始值和终止值的。此处创建了范围在0-1之间等距的500个值组成的序列。
plt.figure(figsize=(10,4))
plt.figure( ) 创建一个图像,可以理解为一张空白的画布,其中的参数 figsize 可以控制画布的大小。在信号处理中,信号的时域波形和频谱的长宽比较大。此处创建了10×4大小的图像。这行代码下面的命令都是在这张画布的基础上进行绘图。
plt.plot(t,y)
plt.plot(a,b) 作出b关于a变化的图像,a和b是相同长度的np.ndarray对象,可由 np.linspace( ) 创建。此时a为自变量,b为因变量,该函数会将相邻的(a,b)点(横坐标为a中的值,纵坐标为b中对应的值)之间用直线相连。为了得到看上去平滑的曲线,需要减少相邻点的距离,即增加参与作图的点的个数,因此前面横坐标在0和1之间取了500个点。
连续信号与离散信号
信号可以分为连续信号和离散信号,连续信号在相应的时间区间内处处有值,且信号强度随着时间变化而连续变化,而离散信号只在特定的某些时间点有值。上面所作的正弦信号即为连续信号。
通常,作连续信号的图像时使用plt.plot命令将每个时间点对应的信号值相连,时间点越密集,曲线越平滑。同样的正弦信号在同样的时间区间内,下图是仅取100个时间点使用plt.plot命令后的效果:
可以看到出现了很多尖锐且不连续的部分。
离散时间信号的图像常用plt.stem命令,该命令会将各时间点的信号强度作为一个孤立的点进行绘制。例如,绘制信号
的图像,可采用以下代码:
#导入所需的包
import numpy as np
import matplotlib.pyplot as plt
f=0.1
t=np.linspace(0 , 10 , 11) #在0-10中均匀取11个点,即0,1,2...10
y=np.sin( 2*np.pi*f * t)
plt.figure(figsize=(10,4)) #创建一张10×4大小的图像
plt.stem(t,y) #作出离散信号图像
plt.show()
print(type(t))
作出的图像如图:
模拟信号与数字信号
若将离散时间信号在各个时间点上的信号幅值也取离散值,就形成了数字信号,数字信号具有易于传输、抗干扰能力强等特点;与之相反,在时间和幅值上都是连续的时间信号有时也称为模拟信号,自然界中的信号均为模拟信号。
利用Python绘制常见信号
接下来介绍一些常见信号在python中的绘制方法,同时穿插一些常见的画图函数的用法。
方波信号
在python中,可以利用Scipy中的signal模块中的square函数绘制方波。其用法如下:
singnal.square(t,duty=0.5) 传入两个参数,第一个是时间序列,是np.ndarray对象,第二个参数是占空比,默认为0.5,即50%。要注意的是,该函数产生的方波默认周期为,
上值为1,
值为-1。若想自己定周期或者频率,比如要想绘制[0,1]上频率为2Hz(即周期为0.5s)的方波,需要使用以下代码
t=np.linspace(0,1,500) #在0-1上取500个点,即信号所在时间序列
f=2
y=signal.square(2*np.pi*f*t) #在时间序列前乘上2*pi*f,是为了获得想要的频率
此代码绘制出的方波信号周期变为除以信号所处的时间序列前面的系数,在
时,函数值为1,在
时,函数值为-1,即以
为周期,前半周期为1,后半周期为-1。
完整代码如下:
#导入所需的包
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
#方波信号
t=np.linspace(0,1,500)
f=2 #2Hz
y=signal.square( 2*np.pi*f*t,duty=0.5) #占空比为0.5的方波信号
plt.figure(figsize=(8,4))
plt.plot(t,y)
plt.show()
作出的方波如图所示
三角波信号
在python中,可以利用Scipy中的signal模块中的sawtooth函数绘制三角波。其用法如下:
signal.sawtooth(t,width), 第一个参数square函数相同,第二个参数指的是三角波的上升部分时间占一个周期的比例,取值范围为[0,1],默认为1,即在一整个周期都处于上升状态。若取值为0.5,则一个周期的前半部分上升,后半部分下降,此时,上升部分和下降部分所占时间相同。三角波周期和频率的计算与方波类似。比如,在[0,1]上作出频率为5Hz的三角波图像。width值分别取0.5和1,代码如下:
#导入所需的包
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
#三角波信号
t=np.linspace(0,1,500)
f=5 #5Hz
y1=signal.sawtooth( 2*np.pi*f*t,width=0.5) #周期为2*pi/(2*pi*f) = 1/f
y2=signal.sawtooth( 2*np.pi*f*t,width=1)
plt.figure(figsize=(12,4))
plt.subplot(1,2,1) #第一幅图
plt.plot(t,y1)
plt.title('width=0.5,f=5Hz') #添加标题
plt.subplot(1,2,2) #第二幅图
plt.plot(t,y2)
plt.title('width=1,f=5Hz') #添加标题
plt.show()
作出结果如下:
下面简单解释一下其中用到的部分作图函数
plt.subplot(1,2,1)
plt.subplot(raw,column,num)可将画布分成raw行,column列,共raw×column个分画布,并在第1个分画布上绘图,其序号从左往右,从上往下依次增大。这行代码就是将原来的大画布分成了一行两列,并在第一个(即左侧)子画布上绘图。
plt.title('width=0.5,f=5Hz')
plt.title(text)顾名思义,给当前画布起个标题。
复指数信号
复指数信号是形如的信号,其中
,利用欧拉公式可将该信号分解如下:
此时,该信号的实部与虚部分别包含了余弦信号和正弦信号,且都乘上了一个指数律变化的因子。复指数信号在现实中无法实现,但其包含了很多常见的信号。以其实部为例,利用以下代码对比不同的和
值对信号
的影响
#导入所需的包
import numpy as np
import matplotlib.pyplot as plt
t=np.linspace(0,5,500)
sigma1=1 #不同的参数值
sigma2=0
sigma3=-1
omega1=4*np.pi
omega2=0
K=1
plt.figure(figsize=(9,9))
y1=np.exp(sigma1*t)*np.cos(omega1*t)
y2=np.exp(sigma2*t)*np.cos(omega1*t)
y3=np.exp(sigma3*t)*np.cos(omega1*t)
y4=np.exp(sigma1*t)*np.cos(omega2*t)
plt.subplot(2,2,1) #分成4张子图
plt.plot(t,y1)
plt.title('$\sigma = 1,\omega = 4\pi$')
plt.subplot(2,2,2)
plt.plot(t,y2)
plt.title('$\sigma = 0,\omega = 4\pi$')
plt.subplot(2,2,3)
plt.plot(t,y3)
plt.title('$\sigma = -1,\omega = 4\pi$')
plt.subplot(2,2,4)
plt.plot(t,y4)
plt.title('$\sigma = 1,\omega = 0$')
plt.show()
得到图像:
由图及理论计算可知:
当时,为增幅正弦信号
当时,为等幅正弦信号
当时,为减幅正弦信号
当时,为指数信号
显然,当时,为直流信号
抽样信号
我们把形如的信号称为抽样信号,记为
,该信号在之后会经常用到。在python中可以利用辛格函数
产生抽样信号,使用np.sinc()进行绘制,代码如下:
#导入所需的包
import numpy as np
import matplotlib.pyplot as plt
#抽样信号
t=np.linspace(-5*np.pi,5*np.pi,500)
y=np.sinc(t/np.pi)
plt.figure()
plt.plot(t,y)
plt.show()
作出的图像: