任意加权的移动平均(低通和高通滤波器)

时间:2019-01-29 11:32:28

标签: signal-processing kdb

给出输入信号x(例如,电压,每秒每秒采样两千次,几分钟),我想计算例如

/ this is not q
y[3] = -3*x[0] - x[1] + x[2] + 3*x[3]
y[4] = -3*x[1] - x[2] + x[3] + 3*x[4]
. . .

我的目标是可变的窗户长度和重量系数。如何在q中完成?我知道mavgsignal processing in qmoving sum qidiom

在DSP世界中,这被称为通过进行卷积来应用滤波器内核。权重系数定义内核,内核构成高通或低通滤波器。上面的示例从最后四个点计算斜率,并通过最小二乘法将直线放置。

3 个答案:

答案 0 :(得分:3)

对于参数可设置的系数,这样的事情会起作用:

q)x:10+sums -1+1000?2f
q)f:{sum x*til[count x]xprev\:y}
q)f[3 1 -1 -3] x
0n 0n 0n -2.385585 1.423811 2.771659 2.065391 -0.951051 -1.323334 -0.8614857 ..

某些情况下可以更快一些(运行0 xprev并不是最好的选择)

q)g:{prev[deltas x]+3*x-3 xprev x}
q)g[x]~f[3 1 -1 -3]x
1b
q)\t:100000 f[3 1 1 -3] x
4612
q)\t:100000 g x
1791

如果您对此领域感兴趣,请在q中有一份kx信号处理白皮书:https://code.kx.com/q/wp/signal-processing/

答案 1 :(得分:0)

如果输入列表不大,则可以使用此处提到的技术: https://code.kx.com/q/cookbook/programming-idioms/#how-do-i-apply-a-function-to-a-sequence-sliding-window

使用“扫描”副词。在此过程中,会创建多个列表,这对于大列表而言可能效率不高。

使用扫描的其他解决方案是:

func touch(touch: UITouch){
  let touchLocation = touch.location(in: mapIso)
  var touchPos2D = pointIsoTo2D(p: touchLocation)

  if let characterEntity = entities.first(where: { (entity) -> Bool in
    return entity.isKind(of: BigBlue.self)
  }){
    if let movementComponent = characterEntity.component(ofType: MovementComponent.self), let spriteComponent = characterEntity.component(ofType: SpriteComponent.self){

      // Create path and move from 2D map
      let nodes2D = entities.filter { (entity) -> Bool in
        return entity.component(ofType: SolidComponent.self) != nil && entity != characterEntity
        }.compactMap { (entity) -> SKSpriteNode? in
          return entity.component(ofType: SpriteComponent.self)?.node2D
      }

      // Highlight obstacles
      nodes2D.forEach { (node) in
        node.color = UIColor.blue
        node.colorBlendFactor = 0.5
      }

      let obstacles = SKNode.obstacles(fromNodeBounds: nodes2D)
      let path = find2DPath(from: spriteComponent.node2D!.position, to: touchPos2D, obstacles: obstacles)
      movementComponent.move(from: path)
    }
  }
}

此功能还会创建多个列表,因此对于大列表来说可能又不是很有效。

其他选项是使用索引从输入列表中获取目标项目并执行计算。这将仅在输入列表上起作用。

 q)f:{sum y*next\[z;x]} / x-input list, y-weights, z-window size-1
 q)f[x;-3 -1 1 3;3]

这是一个非常基本的功能。您可以根据需要向其添加更多变量。

答案 2 :(得分:0)

这可能有点陈旧,但我想我应该考虑一下。去年我写了一篇有关信号处理的论文,可能有一定价值。根据您使用的信号大小,仅在KDB内工作,通过内核/窗口和信号之间基于FFT的卷积,您将看到更好的性能。

但是,我只编写了一个简单的基数2 FFT,尽管在我的github存储库中,我确实有未经测试的工作,它可以使用更灵活的Bluestein算法,该算法将允许更多可变的信号长度。 https://github.com/callumjbiggs/q-signals/blob/master/signal.q

如果您希望通过移动总和执行完全手动卷积的路径,那么最好的方法是将其分解为等于内核/窗口大小的块(这是基于Arthur W的工作)多年前做的

q)vec:10000?100.0
q)weights:30?1.0
q)wsize:count weights
q)(weights$(((wsize-1)#0.0),vec)til[wsize]+) each til count v
32.5931 75.54583 100.4159 124.0514 105.3138 117.532 179.2236 200.5387 232.168.