【问题标题】:Trapezoidal wave in PythonPython中的梯形波
【发布时间】:2017-11-16 07:20:57
【问题描述】:

如何在 Python 中生成梯形波?

我查看了 SciPy 和 NumPy 等模块,但没有成功。是否有诸如 scipy.signal.gaussian 之类的模块返回代表高斯函数波的值数组?

我使用Astropy的梯形内核生成了这个, Trapezoid1DKernel(30,slope=1.0) .我想在不使用 Astropy 的情况下在 Python 中实现它。

【问题讨论】:

  • 你的梯形波有什么参数?
  • 只有宽度和坡度。

标签: python-3.x numpy matplotlib scipy


【解决方案1】:

从SciPy website 看来,这似乎不包括在内(他们目前有sawtooth 和square,但不包括梯形)。作为the C 示例的通用版本,以下将做你想做的事,

import numpy as np
import matplotlib.pyplot as plt

def trapezoidalWave(xin, width=1., slope=1.):
    x = xin%(4*width)
    if (x <= width):
        # Ascending line
        return x*slope;
    elif (x <= 2.*width):
        # Top horizontal line
        return width*slope
    elif (x <= 3.*width):
        # Descending line
        return 3.*width*slope - x*slope
    elif (x <= 4*width):
        # Bottom horizontal line
        return 0.


x = np.linspace(0.,20,1000)
for i in x:
    plt.plot(i, trapezoidalWave(i), 'k.')
    plt.plot(i, trapezoidalWave(i, 1.5, 2.), 'r.')
plt.show()

看起来像,

这可以通过允许您使用 NumPy 数组的 Heaviside 函数更优雅地完成,

import numpy as np
import matplotlib.pyplot as plt

def H(x):
    return 0.5 * (np.sign(x) + 1)

def trapWave(xin, width=1., slope=1.):
    x = xin%(4*width)
    y = ((H(x)-H(x-width))*x*slope +
         (H(x-width)-H(x-2.*width))*width*slope +
         (H(x-2.*width)-H(x-3.*width))*(3.*width*slope - x*slope))
    return y

x = np.linspace(0.,20,1000)
plt.plot(x, trapWave(x))
plt.plot(x, trapWave(x, 1.5, 2.))
plt.show()

对于这个例子,Heaviside 版本的速度大约快 20 倍!

【讨论】:

    【解决方案2】:

    下面的例子展示了如何获取分数和显示范围。

    基于回复的公式:Equation for trapezoidal wave equation

    import math
    import numpy as np
    import matplotlib.pyplot as plt
    
    
    def get_wave_point(x, a, m, l, c):
        # Equation from: https://stackoverflow.com/questions/11041498/equation-for-trapezoidal-wave-equation
        # a/pi(arcsin(sin((pi/m)x+l))+arccos(cos((pi/m)x+l)))-a/2+c
        # a is the amplitude
        # m is the period
        # l is the horizontal transition
        # c is the vertical transition
    
        point = a/math.pi*(math.asin(math.sin((math.pi/m)*x+l))+math.acos(math.cos((math.pi/m)*x+l)))-a/2+c
        return point
    
    print('Testing wave')
    
    x = np.linspace(0., 10, 1000)
    listofpoints = []
    for i in x:
        plt.plot(i, get_wave_point(i, 5, 2, 50, 20), 'k.')
        listofpoints.append(get_wave_point(i, 5, 2, 50, 20))
    print('List of points : {} '.format(listofpoints))
    plt.show()
    

    【讨论】:

      【解决方案3】:

      虽然宽度和斜率足以定义三角信号,但您需要梯形信号的第三个参数:幅度。

      使用这三个参数,您可以轻松调整scipy.signal.sawtooth 函数,通过截断和偏移三角形函数为您提供梯形。

      from scipy import signal
      import matplotlib.pyplot as plt
      import numpy as np
      
      
      def trapzoid_signal(t, width=2., slope=1., amp=1., offs=0):
          a = slope*width*signal.sawtooth(2*np.pi*t/width, width=0.5)/4.
          a[a>amp/2.] = amp/2.
          a[a<-amp/2.] = -amp/2.
          return a + amp/2. + offs
      
      t = np.linspace(0, 6, 501)
      plt.plot(t,trapzoid_signal(t, width=2, slope=2, amp=1.), label="width=2, slope=2, amp=1")
      plt.plot(t,trapzoid_signal(t, width=4, slope=1, amp=0.6), label="width=4, slope=1, amp=0.6")
      
      plt.legend( loc=(0.25,1.015))
      plt.show()
      

      请注意,您可能还想根据用例定义一个阶段。

      为了定义单个脉冲,您可能需要稍微修改函数并提供一个范围超过[0,width] 的数组。

      from scipy import signal
      import matplotlib.pyplot as plt
      import numpy as np
      
      def trapzoid_signal(t, width=2., slope=1., amp=1., offs=0):
          a = slope*width*signal.sawtooth(2*np.pi*t/width, width=0.5)/4.
          a += slope*width/4.
          a[a>amp] = amp
          return a + offs
      
      for w,s,a in zip([2,5], [2,1], [1,0.6]):
          t = np.linspace(0, w, 501)
          l = "width={}, slope={}, amp={}".format(w,s,a)
          plt.plot(t,trapzoid_signal(t, width=w, slope=s, amp=a), label=l)
      
      plt.legend( loc="upper right")
      plt.show()
      

      【讨论】:

      • 这看起来很方便。你能告诉我如何只产生一个特定宽度的单个脉冲吗?我想实现我在问题中附加的图像。谢谢
      • 非常感谢。做了一些修改,终于完成了。
      【解决方案4】:

      全部功劳归于@ImportanceOfBeingErnest。我只是对他的代码进行了一些修改,这让我很开心。

      from scipy import signal
      import matplotlib.pyplot as plt
      from matplotlib import style
      import numpy as np
      
      def trapzoid_signal(t, width=2., slope=1., amp=1., offs=0):
          a = slope*width*signal.sawtooth(2*np.pi*t/width, width=0.5)/4.
          a += slope*width/4.
          a[a>amp] = amp
          return a + offs
      
      for w,s,a in zip([32],[1],[0.0322]):
          t = np.linspace(0, w, 34)
      
          plt.plot(t,trapzoid_signal(t, width=w, slope=s, amp=a))
      
      
      plt.show()
      

      结果:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-04
        • 1970-01-01
        • 1970-01-01
        • 2014-12-17
        • 2018-01-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多