在 Numpy 中的局部最小值之前分割信号

split signal right before local minima in Numpy

考虑以下名为 final1 的 numpy 数组(信号):

我想把之前的数组分成4个子数组。四个子数组在局部最小值之前的时刻分开,如下图所示:

我的想法是找到数组的局部最小值和最大值索引和值:

minimaindex = argrelextrema(final1, np.less)
maximaindex = argrelextrema(final1, np.greater)
valuesminima = final1[argrelextrema(final1, np.greater)[0]]
valuesmaxima = final1[argrelextrema(final1, np.less)[0]]

然后根据值数组对索引数组进行排序,考虑 4 个最大的最小值,最后找到与四个最小值最接近的最大值,并根据这些值的索引拆分 final1 数组。

我想知道是否有人对如何完成最后一部分有建议。

谢谢

编辑: 这是信号向量: https://app.box.com/s/isog7pa3xcradzcsivn5vtx7mj8u0wp1

您可以使用 argsort 获取较小最小值的索引:

valuesminima = final1[minimaindex]
# Find 4 smaller minimas
idx = np.argsort(valuesminima) # sort minima
target = idx[:4] # 4 smaller minimas

# Find all maximas
argmaximas = argrelextrema(final1, np.less)

# Extract maximas closest to the minimas
maximas = []
for minidx in minimaindex[target]: # for each minima
    dist = np.abs(argmaximas - minidx) # distance current minima
    maximas += [np.argmin(dist)] # get the closest maxima

不太花哨,但我想它可以工作。 maximas 包含最接近较小的 4 个最小值的 4 个最大值。

我不确定接受的答案通常会按照您在图表上显示的那样进行。我当然不能让它产生正确的答案!

通常,您总是会得到交替的最大值和最小值,其中 none 的边缘情况是一个或两个。您需要查看所有在它们之前有最大值的最小值,而无需搜索所有最大值以查看哪个最近。此外,您的图表上只有三个切点。

您有很多 "noise" 最大值和最小值,这很容易打乱您的结果 - 进行一些平滑处理是个好主意。此外,您使用 argrelextrema 的方式实际上与

相同
np.where((a[:-2] > a[1:-1]) & (a[1:-1] < a[2:]))

(这可能会更快,但您必须 +1 来索引值)两者都会错过一个恰好有两个值相同的转折点。

无论如何,这似乎对我有用你的数据:

import numpy as np
from scipy import signal

final1 = np.loadtxt("/home/jill/Downloads/256frames_timed_SumrowSignal_1.csv", delimiter=",")
#final1 = np.convolve(final1, [0.1, 0.2, 0.4, 0.2, 0.1])

minimaindex = signal.argrelextrema(final1, np.less)[0]
maximaindex = signal.argrelextrema(final1, np.greater)[0]

if minimaindex[0] < maximaindex[0]: # ensure all minima have a previous maxima
  minimaindex = minimaindex[1:]
maximaindex = maximaindex[:len(minimaindex)]
diffs = final1[maximaindex] - final1[minimaindex]
diffs_as = np.argsort(diffs)[-3:]
cut_points = maximaindex[diffs_as]

编辑如果您查看所附图片,您会发现您总是必须交替使用最大值和最小值 - 因为它们是什么。

您必须注意的情况是第一个最小值的左侧没有最大值点。这就是我检查每个索引的第一个索引的行所做的。如果最大值不是第一个,它会砍掉第一个最小值。它还必须确保最大值列表被截断为与最小值相同的长度。

我不检查的情况就像下面两行。如果没有足够的最小值或最大值,您可以在这里停止该过程:

if minimaindex[0] < maximaindex[0]: # ensure all minima have a previous maxima
  minimaindex = minimaindex[1:]
if len(minimaindex) < 3 or len(maximaindex) < 3:
  error_message = "not enough peaks"
  return None #break, exit, whatever is relevant to the way you use the code
maximaindex = maximaindex[:len(minimaindex)]