【问题标题】:Python signal counterPython信号计数器
【发布时间】:2017-04-02 16:56:51
【问题描述】:

我有两个从实验中获取的数据数组; x(时间)和 y(电压)。这些绘制在下面。每 200 微秒,信号处于以下三种状态之一:

  1. 取负值(即
  2. 取正值(即 > 0.3 V)
  3. 保持在噪声水平(即~0 到 0.1 V 之间)

我想“数字化”这个信号,以便案例 1.、2. 和 3. 对应于离散值 -1、+1 或 0。

如何通过分析数据数组来做到最好?

我目前的想法:

  • 进行插值以找到 y 满足每个阈值的 x 值。

np.interp(0.5,x,y)

问题:

  • 如何对满足 y 阈值的多个位置执行此操作?

【问题讨论】:

  • 您似乎已经解决了问题;您只需将案例直接转换为代码即可。您在确定阈值方面还有其他问题吗?
  • 你已经知道你想要的行为,那么你可以简单地编写一个实现该行为的函数并将其映射到你的数据上吗?
  • 我提到我不确定如何执行此操作,以便计算跟踪中满足阈值的所有位置,而不仅仅是np.interp() 返回的第一种情况跨度>

标签: python signals analysis


【解决方案1】:

对于 N 个阈值,有 N+1 个级别。使用以下步骤找到平交道口:

  • 遍历所有样本,然后遍历阈值,
  • 通过比较绝对值组合的乘积来检查当前水平和样本是否存在交叉,例如:abs(y1)*y0 != y1*abs(y0)
  • 如果发生了平交道口,则使用线性方程找到交叉口的 x 值。
  • 斜坡的极性告诉您交叉点是来自低于或高于的水平,指示当前水平。

下面的函数实现了上面的:

def quantizer(time,voltage,thresholds):
    x0=time[0]; y0=voltage[0];
    l0 = 0
    for level,thresh in enumerate(thresholds):
        l0 = level if y0>thresh else l0
    xings=[tuple([x0,l0])]
    for x1,y1 in zip(time[1:],voltage[1:]):
        xings_i=[]
        dy=y1-y0
        dx=x1-x0
        dy_dx = dy/dx
        for level,thresh in enumerate(thresholds):
            y1s=y1-thresh
            y0s=y0-thresh
            if dy!=0:
                if abs(y1s)*y0s!=y1s*abs(y0s):
                    xings_i.append(tuple([x0-y0s/dy_dx,level+1*(dy_dx>0)]))
        xings_i.sort(key=lambda tup: tup[0])
        xings+=xings_i
        x0=x1
        y0=y1
    return xings

以下输入用于测试功能:

time =    [  0,   1,   2,   3,   4 ]
voltage = [-2.0,-1.2, 2.0, 1.1,-4.0]
thresholds = [-0.25,0.3]

这个函数返回的级别是无符号的,从零开始,所以函数的结果下移了一个:

def main():
    for t,level in quantizer(time,voltage,thresholds):
        print(str(round(t,2)) + "\t" + str(level-1))

结果如下:

0       -1
1.3     0
1.47    1
3.16    0
3.26    -1

【讨论】:

    【解决方案2】:

    假设您将我们的数据保存在 pandas 数据表中(data 具有列 xy),我会先清理一下您的数据(将其数字化)。

    data.loc[data['y'] > 0.3, 'y'] = +1
    data.loc[data['y'] < -0.25, 'y'] = -1
    data.loc[(data['y'] >= -0.25) & (data['y'] <= 0.3), 'y'] = 0
    

    战后我会通过计算后续元素之间的差异来检查斜率

    data_diff = data.set_index('x').diff(periods=1, axis=0)
    

    现在遍历您的差异并计数

    state = 0
    pos_peaks = 0
    neg_peaks = 0
    flats = 0
    for row in data_diff.itertuples():
        if row[1] > 0 and state == 0:
            pos_peaks += 1
            state = 1
        elif row[1] < 0 and state == 0:
            neg_peaks +=1
            state = -1
        elif row[1] < 0 and state == 1:
            flats += 1
            state = 0
        elif row[1] > 0 and state == -1:
            flats += 1
            state = 0
    

    【讨论】:

    • 不使用熊猫。 .diff的目的是什么?
    • .diff() 是 pandas 中的一个函数,用于计算沿轴的差异。在给定的情况下,它会计算后续行之间的差异。见stackoverflow.com/a/13115473/4141279
    【解决方案3】:

    作为解决方案之一,您可以将它们替换为所需的值:

     >>> a=np.random.rand(10)-0.5  # just for test
     >>> a
     array([-0.16532652,  0.17079655, -0.08183734, -0.42446642, -0.15749626,
             0.31809266,  0.09871911,  0.10324168,  0.43021048,  0.16749866])
     >>> a[a<-0.3] = -1
     >>> a[a>0.25] = +1
     >>> a
     array([-0.16532652,  0.17079655, -0.08183734, -1.        , -0.15749626,
             1.        ,  0.09871911,  0.10324168,  1.        ,  0.16749866])
     >>> a[(a>-1) & (a<1)]=0
     >>> a
     array([ 0.,  0.,  0., -1.,  0.,  1.,  0.,  0.,  1.,  0.])
     >>>
    

    【讨论】:

      【解决方案4】:

      您可以通过像my_array &gt; 0.3 这样的检查来离散化数据,这会返回一个布尔数组,该数组可以转换为 1 和 0:np.array( my_array &gt; 0.3 ,int)

      可以通过从信号中减去移位信号(插入信号第一个元素的副本)来找到跳跃的位置:

      def jump(time,signal):
          d_signal      = np.array(signal>.3,int) -np.array(signal<-.25,int)
          shift         = d_signal - np.insert(d_signal,0,d_signal[0])[:-1]
          time_of_jump  = time[shift!=0]
          jump_to_value = d_signal[shift!=0]
      
          return time_of_jump,jump_to_value
      

      我已经在一些看起来与你的有点相似的随机信号上对此进行了测试:

      import numpy as np
      import matplotlib.pyplot as plt
      
      jumps=np.around(np.random.rand(30)*2-1)*.5
      signal=np.array([])
      
      for i in jumps:
          signal=np.hstack((signal , np.ones(10)*i + np.random.normal(0,.05,10)))
      time=np.arange(0,len(signal))*.01+239
      
      print(jump(time,signal)) # Python 3
      print jump(time,signal)  # Python 2
      

      返回发生跳跃的时间数组(具有新值的第一个元素)和信号已跳跃到的值 (+1,0,-1)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-19
        • 2012-01-27
        • 2021-12-16
        • 1970-01-01
        • 2023-03-11
        相关资源
        最近更新 更多