使用numpy在重复信号的一部分内绘制抛物线 [英] plotting a parabola within part of a repeating signal using numpy

查看:131
本文介绍了使用numpy在重复信号的一部分内绘制抛物线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个重复信号,该信号随过程的每个周期(几乎每秒重复一次)而略有变化,尽管在某些参数内每个周期的持续时间和内容彼此略有不同.我的信号数据的每一秒都有一千个x,y坐标.每个周期中一小段但很重要的数据段已损坏,我想用朝上的抛物线替换每个损坏的段.

对于每个需要用抛物线替换的数据段,我都有三个点的x,y坐标.顶点/最小值是这些点之一.另外两个点是向上的U形(即抛物线)的左上角和右上角.换句话说,左上角是此函数域中最低x值的x,y坐标对,而右上角是此函数域中最高x值的x,y坐标对.左上角和右上角的y坐标彼此相等,并且是数据段中的两个最高y值.

如何编写代码以绘制此朝上抛物线中的其余数据点?请记住,每分钟数据需要调用此函数60或70次,并且形状每次调用此函数时,抛物线的/formula都需要更改,以便解决每个结果抛物线中这三对x,y坐标之间的不同关系.

def ReplaceCorruptedDataWithParabola(Xarray, Yarray, LeftTopX, LeftTopY
                                     , LeftTopIndex, MinX, MinY, MinIndex
                                     , RightTopX, RightTopY, RightTopIndex):  

    # Step One: Derive the formula for the upward-facing parabola using 
    # the following data from the three points:
        LeftTopX,LeftTopY,LeftTopIndex  
        MinX,MinY,MinIndex  
        RightTopX,RightTopY,RightTopIndex 

    # Step Two: Use the formula derived in step one to plot the parabola in
    # the places where the corrupted data used to reside:
    for n in Xarray[LeftTopX:RightTopX]:
        Yarray[n]=[_**The formula goes here**_]

    return Yarray 

注意:Xarray和Yarray都是单列向量,每个索引处都有数据,这些数据将两个数组作为x,y坐标集链接在一起.它们都是numpy数组. Xarray包含时间信息,并且不会改变,但是Yarray包含信号数据,包括损坏的线段,该段将被需要通过此函数计算的抛物线数据替换.

解决方案

因此,据我了解,您有3个点想适合抛物线.

通常,仅使用 numpy.polyfit a>,但是如果您真的担心速度,并且恰好要拟合三点,那么使用最小二乘拟合就没有意义了.

相反,我们有一个偶数确定的系统(将抛物线拟合到3 x,y点),并且可以用简单的线性代数获得精确的解.

因此,总而言之,您可能会执行以下操作(大多数操作是在绘制数据):

import numpy as np                                                                              
import matplotlib.pyplot as plt                                                                 

def main():
    # Generate some random data
    x = np.linspace(0, 10, 100)
    y = np.cumsum(np.random.random(100) - 0.5)

    # Just selecting these arbitrarly 
    left_idx, right_idx = 20, 50      
    # Using the mininum y-value within the arbitrary range
    min_idx = np.argmin(y[left_idx:right_idx]) + left_idx 

    # Replace the data within the range with a fitted parabola
    new_y = replace_data(x, y, left_idx, right_idx, min_idx)  

    # Plot the data
    fig = plt.figure()
    indicies = [left_idx, min_idx, right_idx]

    ax1 = fig.add_subplot(2, 1, 1)
    ax1.axvspan(x[left_idx], x[right_idx], facecolor='red', alpha=0.5)
    ax1.plot(x, y)                                                    
    ax1.plot(x[indicies], y[indicies], 'ro')                          

    ax2 = fig.add_subplot(2, 1, 2)
    ax2.axvspan(x[left_idx], x[right_idx], facecolor='red', alpha=0.5)
    ax2.plot(x,new_y)                                                 
    ax2.plot(x[indicies], y[indicies], 'ro')

    plt.show()

def fit_parabola(x, y):
    """Fits the equation "y = ax^2 + bx + c" given exactly 3 points as two
    lists or arrays of x & y coordinates"""
    A = np.zeros((3,3), dtype=np.float)
    A[:,0] = x**2
    A[:,1] = x
    A[:,2] = 1
    a, b, c = np.linalg.solve(A, y)
    return a, b, c

def replace_data(x, y, left_idx, right_idx, min_idx):
    """Replace the section of "y" between the indicies "left_idx" and
    "right_idx" with a parabola fitted to the three x,y points represented
    by "left_idx", "min_idx", and "right_idx"."""
    x_fit = x[[left_idx, min_idx, right_idx]]
    y_fit = y[[left_idx, min_idx, right_idx]]
    a, b, c = fit_parabola(x_fit, y_fit)

    new_x = x[left_idx:right_idx]
    new_y = a * new_x**2 + b * new_x + c

    y = y.copy() # Remove this if you want to modify y in-place
    y[left_idx:right_idx] = new_y
    return y

if __name__ == '__main__':
    main()

希望能有所帮助...

I have a repeating signal that varies a little bit with each cycle of a process that repeats roughly every second, though the duration and the contents of each cycle vary from each other a little bit within some parameters. There are a thousand x,y coordinates for every second of my signal data. A small, but important, segment of the data within each cycle is corrupted, and I want to replace each corrupted segment with an upward facing parabola.

For each data segment that needs to be replaced by the parabola, I have the x,y coordinates of three points. The vertex/minimum is one of those points. And the other two points are the left and right tops of the upward-facing U-shape that is the parabola. In other words, the left top is the x,y coordinate pair of the lowest x value in the domain of this function, while the right top is the x,y coordinate pair of the highest x value in the domain of this function. The y-coordinates of the left top and right top are equal to each other, and are the two highest y-values in the data segment.

How can I write the code to plot the remaining data points in this upward facing parabola? Remember that this function needs to be called 60 or 70 times for every minute of data, and that the shape/formula of the parabola will need to change every time this function is called, in order to account for different relationships between these three pairs of x,y coordinates in each resulting parabola.

def ReplaceCorruptedDataWithParabola(Xarray, Yarray, LeftTopX, LeftTopY
                                     , LeftTopIndex, MinX, MinY, MinIndex
                                     , RightTopX, RightTopY, RightTopIndex):  

    # Step One: Derive the formula for the upward-facing parabola using 
    # the following data from the three points:
        LeftTopX,LeftTopY,LeftTopIndex  
        MinX,MinY,MinIndex  
        RightTopX,RightTopY,RightTopIndex 

    # Step Two: Use the formula derived in step one to plot the parabola in
    # the places where the corrupted data used to reside:
    for n in Xarray[LeftTopX:RightTopX]:
        Yarray[n]=[_**The formula goes here**_]

    return Yarray 

Note: Xarray and Yarray are each single-column vectors with data at each index that links the two arrays as sets of x,y coordinates. They are both numpy arrays. Xarray contains time information and does not change, but Yarray contains signal data, including the corrupted segment that will be replaced with the parabolic data that needs to be calculated by this function.

解决方案

So, as I understand it, you have 3 points that you want to fit a parabola to.

Normally, it's simplest to just use numpy.polyfit, but if you're really worried about speed, and you're fitting exactly three points, there's no point in using a least-squares fit.

Instead, we have an even-determined system (fitting a parabola to 3 x,y points), and we can get an exact solution with simple linear algebra.

So, all in all, you might do something like this (most of this is plotting the data):

import numpy as np                                                                              
import matplotlib.pyplot as plt                                                                 

def main():
    # Generate some random data
    x = np.linspace(0, 10, 100)
    y = np.cumsum(np.random.random(100) - 0.5)

    # Just selecting these arbitrarly 
    left_idx, right_idx = 20, 50      
    # Using the mininum y-value within the arbitrary range
    min_idx = np.argmin(y[left_idx:right_idx]) + left_idx 

    # Replace the data within the range with a fitted parabola
    new_y = replace_data(x, y, left_idx, right_idx, min_idx)  

    # Plot the data
    fig = plt.figure()
    indicies = [left_idx, min_idx, right_idx]

    ax1 = fig.add_subplot(2, 1, 1)
    ax1.axvspan(x[left_idx], x[right_idx], facecolor='red', alpha=0.5)
    ax1.plot(x, y)                                                    
    ax1.plot(x[indicies], y[indicies], 'ro')                          

    ax2 = fig.add_subplot(2, 1, 2)
    ax2.axvspan(x[left_idx], x[right_idx], facecolor='red', alpha=0.5)
    ax2.plot(x,new_y)                                                 
    ax2.plot(x[indicies], y[indicies], 'ro')

    plt.show()

def fit_parabola(x, y):
    """Fits the equation "y = ax^2 + bx + c" given exactly 3 points as two
    lists or arrays of x & y coordinates"""
    A = np.zeros((3,3), dtype=np.float)
    A[:,0] = x**2
    A[:,1] = x
    A[:,2] = 1
    a, b, c = np.linalg.solve(A, y)
    return a, b, c

def replace_data(x, y, left_idx, right_idx, min_idx):
    """Replace the section of "y" between the indicies "left_idx" and
    "right_idx" with a parabola fitted to the three x,y points represented
    by "left_idx", "min_idx", and "right_idx"."""
    x_fit = x[[left_idx, min_idx, right_idx]]
    y_fit = y[[left_idx, min_idx, right_idx]]
    a, b, c = fit_parabola(x_fit, y_fit)

    new_x = x[left_idx:right_idx]
    new_y = a * new_x**2 + b * new_x + c

    y = y.copy() # Remove this if you want to modify y in-place
    y[left_idx:right_idx] = new_y
    return y

if __name__ == '__main__':
    main()

Hope that helps a bit...

这篇关于使用numpy在重复信号的一部分内绘制抛物线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆