2010-10-28 30 views
2

I ont un signal de répétition qui varie un peu avec chaque cycle d'un processus qui se répète à peu près tous les deux, bien que la durée et le contenu de chaque cycle varient les uns des autres un peu dans certains paramètres. Il y a mille coordonnées x, y pour chaque seconde de mes données de signal. Un petit segment, mais important, des données dans chaque cycle est corrompu, et je veux remplacer chaque segment corrompu par une parabole tournée vers le haut.tracé d'une parabole dans une partie d'un signal de répétition en utilisant numpy

Pour chaque segment de données qui doit être remplacée par la parabole, je les coordonnées x, y de trois points. Le sommet/minimum est l'un de ces points. Et les deux autres points sont les sommets gauche et droit de la forme en U orientée vers le haut qui est la parabole. En d'autres termes, le sommet gauche est la paire de coordonnées x, y de la valeur x la plus basse dans le domaine de cette fonction, tandis que le sommet supérieur est la paire de coordonnées x, y de la valeur x la plus élevée du domaine de cette fonction. Les coordonnées y du haut gauche et du haut droit sont les mêmes et sont les deux valeurs y les plus élevées dans le segment de données.

Comment puis-je écrire le code pour tracer les points de données restant dans cette parabole tournée vers le haut? Rappelez-vous que cette fonction doit être appelée 60 ou 70 fois pour chaque minute de données, et que la forme/formule de la parabole devra changer chaque fois que cette fonction est appelée, afin de tenir compte des différentes relations entre ces trois paires des coordonnées x, y dans chaque parabole résultante.

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 et Yarray sont chacun des vecteurs à une seule colonne avec des données à chaque index qui relie les deux réseaux comme des ensembles de coordonnées x, y. Ils sont tous les deux des tableaux chiffrés. Xarray contient des informations de temps et ne change pas, mais Yarray contient des données de signal, y compris le segment corrompu qui sera remplacé par les données paraboliques qui doivent être calculées par cette fonction.

Répondre

6

Donc, si je comprends bien, vous avez 3 points que vous souhaitez installer un à parabola.

Normalement, il est plus simple d'utiliser numpy.polyfit, mais si vous êtes vraiment inquiet au sujet de la vitesse, et que vous ajustez exactement trois points, il ne sert à rien d'utiliser un ajustement par les moindres carrés.

Au lieu de cela, nous avons un système encore déterminé (montage d'une parabole à 3 x, y) des points, et nous pouvons obtenir une solution exacte avec simple, algèbre linéaire.

Ainsi, dans l'ensemble, vous pourriez faire quelque chose comme ça (la plupart de ces complote les données):

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() 

Example plot

espoir qui aide un peu ...

+0

+ 1 belle réponse. – zellus