信号与系统实验之信号的时域分析(Python+matplotlib)

信号是随时间和空间变化的某种物理量,它一般是时间变量t的函数。信号随时间变量t变化的函数曲线成为信号的波形。

本部分主要内容包括两块:

  1. 信号的时域变换
  2. 信号的基本运算

下面我将用Python+matplotlib的方式绘制动态图,从而直观地展示效果

1. 信号的时域变换

基本原理

信号在时域中的变换基本包括:

  1. 反转:信号的时域反转就是将信号f (t) 的波形以纵轴为对称轴为轴翻转180。其表达式为f(-t)。
  2. 时移:信号的时移就是将信号f(t)的波形沿时间轴t平移,但波形的形状不变。其表达式为f(t+t0),t0为正时左移,t0为负时右移。
  3. 展缩:信号的展缩就是将信号f(t)在时间轴上展缩或压缩,但纵轴上的值不变。其表达式为f(at),a>1时为压缩,a<1时为展宽。

下面来具体看一下这三种变换该如何实现,在这之前,先确定一个原来信号,下面的变换将在原信号的基础上进行:

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0, 4), ylim=(-4, 4))
line, = ax.plot([], [], lw=2)

# initialization function: plot the background of each frame
def init():
    line.set_data([], [])
    return line,

# animation function.  This is called sequentially
def animate(i):
    x = np.linspace(0, 4, 1000)
    y = np.sin(np.pi * (x - 0.01 * i))
    line.set_data(x,3*y)
    return line,

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=200, interval=20, blit=True)

plt.show()

效果如下所示:
在这里插入图片描述
这里我把几个比较重要的参数提一下:

  • 横轴、纵轴的长度设置:
    ax = plt.axes(xlim=(0, 4), ylim=(-4, 4))
  • 准备横轴的数据,范围在0-4,生成1000个:
    x = np.linspace(0, 4, 1000)
  • 准备纵轴的数据,求出对应横轴的sin函数值:
    y = np.sin(np.pi * (x - 0.01 * i))
  • 导入数据:
    line.set_data(x, 3*y)

静态图如下:
在这里插入图片描述
为了更好地展示,这里最好是一个子图放两个信号做对比,所以我把代码优化了一下:

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation


# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax1 = plt.axes(xlim=(0, 4), ylim=(-4, 4))
ax2 = plt.axes(xlim=(0, 4), ylim=(-4, 4))
line1, = ax1.plot([], [], lw=2, label='Original signal',color="green")
line2, = ax2.plot([], [], lw=2, label='Transformed signal',color="red")


# initialization function: plot the background of each frame
def init():
    line1.set_data([], [])
    line2.set_data([], [])
    return line1,line2

# animation function.  This is called sequentially
def animate(i):
    x = np.linspace(0, 4, 1000)
    y1 = np.cos(np.pi * (x - 0.01 * i)) #绿色
    y2 = -(np.cos(np.pi * (x - 0.01 * i))) #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=200, interval=20, blit=True)

plt.legend()
plt.show()

加以说明一下:

  • y1用于表示原信号,用绿色表现
  • y2用于表示变换后的信号,用红色表现

下面主要展示的是animate方法里的代码,因为其余部分是不变的,实现以下信号变换,只需要修改几个参数即可,难度也不是很大

反转

反转是以纵轴为中心180度反转,即左右对折

很简单,在x前加个负号即可:

def animate(i):
    x = np.linspace(0, 4, 1000)
    y1 = np.cos(np.pi * (x - 0.01 * i)) #绿色
    y2 = np.sin(np.pi * ((-1) * x - 0.01 * i)) #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

效果如下:
在这里插入图片描述
我们换成指数函数感受一下

这里要把子图的大小稍微改一下:

ax1 = plt.axes(xlim=(-25, 25), ylim=(-4, 100))
ax2 = plt.axes(xlim=(-25, 25), ylim=(-4, 100))

然后再来修改animate方法:

def animate(i):
    x = np.linspace(-4, 4, 1000)
    y1 = 2**x * i #绿色
    y2 = 2**(x*(-1)) * i  #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

在这里插入图片描述

时移

这里我们给定一个值吧,将原信号左移1个单位 :

def animate(i):
    x = np.linspace(0, 4, 1000)
    y1 = np.cos(np.pi * (x - 0.01 * i)) #绿色
    y2 = np.cos(np.pi * (x - 0.01 * i) + 1) #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

在这里插入图片描述
那么向右时移自然是减了,比如向右时移2个单位:

def animate(i):
    x = np.linspace(0, 4, 1000)
    y1 = np.cos(np.pi * (x - 0.01 * i)) #绿色
    y2 = np.cos(np.pi * (x - 0.01 * i) - 2) #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

效果如下:
在这里插入图片描述

展缩

将原信号压缩成原来的一半:

def animate(i):
    x = np.linspace(0, 4, 1000)
    y1 = np.cos(np.pi * (x - 0.01 * i)) #绿色
    y2 = np.cos(np.pi * (x - 0.01 * i) * 2) #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

用动图展示:
在这里插入图片描述
如果要展宽,只需要把值改成小于1的值即可,如展宽成原来的2倍:

def animate(i):
    x = np.linspace(0, 4, 1000)
    y1 = np.cos(np.pi * (x - 0.01 * i)) #绿色
    y2 = np.cos(np.pi * (x - 0.01 * i) * 1/2) #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

效果如下:
在这里插入图片描述

2. 信号的基本运算

实验原理

信号在时域中的运算有相加、相减、相乘、数乘、微分、积分等。

  1. 相加:信号在时域中相加时,其横坐标(时间轴)不变,仅是将横坐标所对应的值相加。两输入加法器:
    在这里插入图片描述
    加法器完成功能:OUT=IN1+IN2

  2. 相减:信号在时域相减时,其横坐标不变,仅是将横坐标值对应的纵坐标值相减。减法器的电路如图所示:
    在这里插入图片描述
    减法器完成功能:OUT=IN2-IN1

  3. 数乘:信号在时域倍乘时,其横坐标不变,仅是将横坐标值所对应的纵坐标值扩大n倍(n>1时扩大;0<n<1时减小)。倍乘器如图所示:
    在这里插入图片描述
    数乘器完成功能:OUT=(RP/R)*IN

  4. 反相:信号在时域反相时,其横坐标不变,仅是将横坐标值所对应的纵坐标值乘负号。反相器电路如图所示:
    在这里插入图片描述
    反相器完成功能:OUT=-IN

  5. 微分:信号在时域微分即是对信号求一阶导数。微分器电路如图所示:
    在这里插入图片描述

  6. 积分:信号在时域积分即将信号在(-∞,t)内求一次积分。积分器电路如图所示:
    在这里插入图片描述

上面这些运算是通过电子元件来实现的,下面我们看一下如何用python实现相加、相减、相乘、数乘、微分、积分

相加

有了上面的基础,下面这几个基本运算其实也很好理解了,不就是多一个信号嘛:

def animate(i):
    x = np.linspace(0, 4, 1000)
    y1 = np.cos(np.pi * (x - 0.01 * i)) #绿色
    y21 = np.sin(np.pi * (x - 0.01 * i))
    y22 = np.sin(np.pi * (x - 0.01 * i))
    y2 = y21 + y22 #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

两个标准的sin函数相加,得到的是:
在这里插入图片描述

这里不需要多说了吧?大家可以尝试改成其他的参数,试一下效果

相减

两个相同的信号相减会得到什么呢:

def animate(i):
    x = np.linspace(0, 4, 1000)
    y1 = np.cos(np.pi * (x - 0.01 * i)) #绿色
    y21 = np.sin(np.pi * (x - 0.01 * i))
    y22 = np.sin(np.pi * (x - 0.01 * i))
    y2 = y22 - y21 #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

答案是一条直线:
在这里插入图片描述

那如果是这种情况,其中一个信号缩减为原来的一半:

def animate(i):
    x = np.linspace(0, 4, 1000)
    y1 = np.cos(np.pi * (x - 0.01 * i)) #绿色
    y21 = np.sin(np.pi * (x - 0.01 * i))
    y22 = np.sin(np.pi * (x - 0.01 * i) * 2)
    y2 = y22 - y21 #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

效果如下:
在这里插入图片描述

当然,这里可以调的参数也有很多,这里就不一一举例了

数乘

这里的数乘不是两个信号相乘,对于某一信号在时域倍乘时,其横坐标不变,仅是将横坐标值所对应的纵坐标值扩大n倍

举个例子,原信号乘2:

def animate(i):
    x = np.linspace(0, 4, 1000)
    y1 = np.sin(np.pi * (x - 0.01 * i)) #绿色
    y2 = 2 * np.sin(np.pi * (x - 0.01 * i))
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

效果如下:
在这里插入图片描述

反相

信号的横坐标不变,仅是将横坐标值所对应的纵坐标值乘负号:

def animate(i):
    x = np.linspace(-4, 4, 1000)
    y1 = np.sin(np.pi * (x - 0.01 * i)) #绿色
    y2 = (-1) * np.sin(np.pi * (x - 0.01 * i)) #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

在这里插入图片描述

这里要注意区分跟反转的区别,我们拿最简单的幂函数举例:

def animate(i):
    x = np.linspace(0, 4, 1000)
    y1 = x * i #绿色
    y2 = x * i * (-1) #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

注意反相是上下对称的:
在这里插入图片描述

微分

我们知道sin(x)的微分是cos(x),所以这里直接改一下即可:

def animate(i):
    x = np.linspace(-4, 4, 1000)
    y1 = np.sin(np.pi * (x - 0.01 * i)) #绿色
    y2 = np.cos(np.pi * (x - 0.01 * i)) #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

图像如下:
在这里插入图片描述

积分

同理,sin(x)在(-∞,t)的积分是-cos(t):
在这里插入图片描述
这样一来就好办了:

def animate(i):
    x = np.linspace(-4, 4, 1000)
    y1 = np.sin(np.pi * (x - 0.01 * i)) #绿色
    y2 = (-1) * np.cos(np.pi * (x - 0.01 * i)) #红色
    line1.set_data(x, y1)
    line2.set_data(x, y2)
    return line1,line2

如下图所示:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zbp_12138/article/details/106392121
今日推荐