给出输入信号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中完成?我知道mavg和signal processing in q和moving sum qidiom
在DSP世界中,这被称为通过进行卷积来应用滤波器内核。权重系数定义内核,内核构成高通或低通滤波器。上面的示例从最后四个点计算斜率,并通过最小二乘法将直线放置。
答案 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.