2016-06-29 71 views
2

我棒做一個動態系統上集成等向ODE如何從python中的離散數據中獲得週期性曲線擬合?

x_ddot + d*x_dot + k*x = a*sin(omega*t) 

與一個修飾:外部力* SIN(歐米加* T)必須被另一個週期信號來代替它是基於某些測量數據。這意味着:我需要對離散測量數據進行曲線擬合,並且所得到的函數必須是週期性的。我有兩個想法如何解決問題:

1)使用傅立葉變換(numpy.fft)。但是使用離散傅立葉變換從離散數據中產生連續函數是很困難的。 2)使用曲線擬合,使用函數如a1 + a2 * sin(omega * t)+ a3 * sin(2 * omega * t)+ a4 * sin(....其中omega是2 * pi /(測量數據的長度)不幸的是,這並不是很成功,我用sin和cos的組合來試驗它,並且進入非常高的階數(... sin(10 *ω* t))沒能更好

Plot

我真的很感激一些提示,請參閱我的代碼示例數據波紋管:

import numpy as np 
from scipy.optimize import curve_fit 
import matplotlib.pyplot as plt 
import math as math 
import scipy.special as sp 

# create data 
f = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1.1,1.3,1.7,1.9,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2.1,2.3,2.9,4.1,4.3,4.4,4.5,4.4,4,3.6,3.2,2.8,2.4,2.0,1.6,1.3,1.2,1.1,1,1,1,1,1] 
alpha = np.linspace(0,len(f),len(f)) 

omega = 2*np.pi/len(f) 

def func(alpha, a1, ac2, ac3, ac4, ac5, ac6, ac7): 
    fit  = a1 + ac2*np.sin(omega*alpha) + ac3*np.sin(omega*2*alpha) + ac4*np.sin(omega*3*alpha) + ac5*np.sin(omega*4*alpha) +  ac6*np.sin(omega*5*alpha) + ac7*np.sin(omega*6*alpha) 
    return fit 

popt, pcov = curve_fit(func, alpha, f) 

print popt 

y_fit= func(alpha,popt[0],popt[1],popt[2],popt[3],popt[4],popt[5],popt[6]) 

plt.plot(alpha,f,'bo',label='discrete data') 
plt.plot(alpha,y_fit,'r',label='periodic fit') 
plt.legend() 
plt.show() 

回答

3

如果您滿足於數值函數,則基於插值的簡單方法如下:

第1步:根據確定函數的一個週期的數據集定義插值函數。 (I用於從SciPy的簡單interp1d,更精細的替代方案,可以在SciPy的。)

from scipy.interpolate import interp1d  
f_interp_one_period = interp1d(alpha, f, 'cubic') 

步驟2:定義基於上述一個周期函數(I用作期間基於所述數據的值55

def f_periodic(alpha): 
     return f_interp_one_period(numpy.mod(alpha,55)) 

以下情節顯示f_periodic超過-100到200的範圍內,和原始數據

enter image description here

+0

謝謝你的回答!不幸的是,我認爲數值函數不能滿足我的問題。我需要像f(t)= k + a * sin(b * t)+ c * sin(d * t)+ ....因爲我使用pydstool – PyNoob

+0

@PyNoob在這種情況下,您可以計算[傅立葉級數近似](http://mathworld.wolfram.com/FourierSeries.html),它需要確定傅立葉係數。相關的文章是[this](http://stackoverflow.com/questions/4258106/how-to-calculate-a-fourier-series-in-numpy) – Stelios