在曲线上查找坡度变化的位置

2024-06-06 03:54:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我有时间和电压的数据点,创建了下面的曲线。在

time数据是

array([  0.10810811,   0.75675676,   1.62162162,   2.59459459,
         3.56756757,   4.21621622,   4.97297297,   4.97297297,
         4.97297297,   4.97297297,   4.97297297,   4.97297297,
         4.97297297,   4.97297297,   5.08108108,   5.18918919,
         5.2972973 ,   5.51351351,   5.72972973,   5.94594595,
         6.27027027,   6.59459459,   7.13513514,   7.67567568,
         8.32432432,   9.18918919,  10.05405405,  10.91891892,
        11.78378378,  12.64864865,  13.51351351,  14.37837838,
        15.35135135,  16.32432432,  17.08108108,  18.16216216,
        19.02702703,  20.        ,  20.        ,  20.        ,
        20.        ,  20.        ,  20.        ,  20.        ,
        20.10810811,  20.21621622,  20.43243243,  20.64864865,
        20.97297297,  21.40540541,  22.05405405,  22.91891892,
        23.78378378,  24.86486486,  25.83783784,  26.7027027 ,
        27.56756757,  28.54054054,  29.51351351,  30.48648649,
        31.56756757,  32.64864865,  33.62162162,  34.59459459,
        35.67567568,  36.64864865,  37.62162162,  38.59459459,
        39.67567568,  40.75675676,  41.83783784,  42.81081081,
        43.89189189,  44.97297297,  46.05405405,  47.02702703,
        48.10810811,  49.18918919,  50.27027027,  51.35135135,
        52.43243243,  53.51351351,  54.48648649,  55.56756757,
        56.75675676,  57.72972973,  58.81081081,  59.89189189])

并且volts数据是

^{pr2}$

plot of the curve

我想确定标记为A、B、C、D和E的点的位置。点A是斜率从零到未定义的第一个位置。点B是直线不再垂直的位置。点C是曲线的最小值。D点是曲线不再垂直的地方。E点是斜率再次接近零的地方。下面的Python代码确定点A和C的位置

tdiff = np.diff(time)
vdiff = np.diff(volts)

# point A
idxA = np.where(vdiff < 0)[0][0]
timeA = time[idxA]
voltA = volts[idxA]

# point C
idxC = volts.idxmin()
timeC = time[idxC]
voltC = volts[idxC]

plot with points A and C

如何确定曲线上由点B、D和E表示的其他位置?在


Tags: 数据time地方np时间diffarray曲线
1条回答
网友
1楼 · 发布于 2024-06-06 03:54:40

您正在查找标记坡度变为或从零或无穷大的任何位置的点。实际上,我们不需要计算任何地方的斜率:yn - yn-1 == 0和{},反之亦然,x也一样。在

我们可以取x的差值。如果两个连续元素中的一个为零,那么diff的diff将是该点的diff或负diff。所以我们只想找到并标记diff(x) == diff(diff(x))和{}的所有点,当然,根据数组之间的大小差异进行适当调整。我们还需要对y同样适用的所有点。在

用新潮的术语来说,这是可以写如下的

def masks(vec):
    d = np.diff(vec)
    dd = np.diff(d)

    # Mask of locations where graph goes to vertical or horizontal, depending on vec
    to_mask = ((d[:-1] != 0) & (d[:-1] == -dd))
    # Mask of locations where graph comes from vertical or horizontal, depending on vec
    from_mask = ((d[1:] != 0) & (d[1:] == dd))
    return to_mask, from_mask

to_vert_mask, from_vert_mask = masks(time)
to_horiz_mask, from_horiz_mask = masks(volts)

请记住,掩码是根据二阶差分计算的,因此它们比输入短两个元素。掩码中的元素对应于输入数组中的元素,在前边和后缘有一个元素的边框(因此下面的索引[1:-1])。可以使用^{}将掩码转换为索引,也可以使用掩码作为索引直接获取x和y值:

^{pr2}$

结果图如下:

enter image description here

请注意,由于分类是分开进行的,“点A”被正确地标识为垂直性开始和水平性结束的位置。问题是,根据这些标准,“E点”似乎无法解决。放大显示所有扩散点正确识别水平线段:

enter image description here

您可以通过完全丢弃from_horiz来选择“E点”的“正确”版本,并且只丢弃to_horiz中的最后一个值:

to_horiz_t, to_horiz_v = apply_mask(to_horiz_mask, time, volts)
to_horiz_t, to_horiz_v = to_horiz_t[-1], to_horiz_v[-1]

plt.plot(time, volts, 'b-')
plt.plot(*apply_mask(to_vert_mask, time, volts), 'r^', label='Plot goes vertical')
plt.plot(*apply_mask(from_vert_mask, time, volts), 'kv', label='Plot stops being vertical')
plt.plot(to_horiz_t, to_horiz_v, 'r>', label='Plot goes horizontal')
plt.legend()
plt.show()

我用这个作为一个展示apply_mask结果的星型展开。结果图为:

{a4}

这正是你要找的情节。丢弃from_horiz也会使“A点”只被标识为垂直下降,这很好。在

正如to_horiz中的多个值所示,此方法对数据中的噪声非常敏感。您的数据非常平滑,但这种方法不太可能用于原始未过滤的测量。在

相关问题 更多 >