2017-10-21 9 views
1

私はscipyからカーブフィットを使ってガウスフィッティングをうまく実装していると思います。しかし、私が取り組んでいる問題は、最適化されたパラメータがセントロイドを変更しているので、フィット感がそれほど大きくないことです。***を使用してガウス関数フィッティングを改善する*** scipyとpythonから3.x

data =np.loadtxt('mock.txt') 
    my_x=data[:,0] 
    my_y=data[:,1] 

    def gauss(x,mu,sigma,A): 
     return A*np.exp(-(x-mu)**2/2/sigma**2) 
    def trimodal_gauss(x,mu1,sigma1,A1,mu2,sigma2,A2,mu3,sigma3,A3): 
     return gauss(x,mu1,sigma1,A1)+gauss(x,mu2,sigma2,A2)+gauss(x,mu3,sigma3,A3) 



    """"" 
    Gaussian fitting parameters recognized in each file 
    """"" 
    first_centroid=(10180.4*2+9)/9 
    second_centroid=(10180.4*2+(58.6934*1)+7)/9 
    third_centroid=(10180.4*2+(58.6934*2)+5)/9 
    centroid=[] 
    centroid+=(first_centroid,second_centroid,third_centroid) 

    apparent_resolving_power=1200 
    sigma=[] 
    for i in range(len(centroid)): 
     sigma.append(centroid[i]/((apparent_resolving_power)*2.355)) 

    height=[1,1,1] 

    p=[]  

    p = np.array([list(t) for t in zip(centroid, sigma, height)]).flatten() 


    popt, pcov = curve_fit(trimodal_gauss,my_x,my_y,p0=p) 

出力:enter image description here

私はピークの多くがここにあることを理解し、私は本当にそれだけで3ガウス分布にフィットする必要があるが、右重心で(私の最初の推測で与えられます)。言い換えれば、私が与える重心が変わらないことを本当に望んでいない。誰もそのような挑戦に遭遇しましたか?それを実現させるためにできることを私に助けてくれますか?

+0

、あなたがより良い、正しい番号に合うだろうと思われますピーク(少なくとも5、おそらく6)のうち、あなたが実際に気にかけている3つの結果だけを取ります。あなたが気にしていないピークが気になる3つのピークの結果に影響を与えるため、あなたの現在のアプローチは悪い仕事をします。それは、追加のものが3つのピークの一部であると「考える」。あなたのコメントのために – NichtJens

答えて

0

、簡単にあなたのガウス関数の重心に境界を置く、あるいはそれらを修正することができます。 Lmfitは、マルチピークモデルの構築も容易にします。

あなたのデータへの完全な例やリンクを与えていないが、あなたのデータへのlmfitとのフィットは次のようになります。一般的には

import numpy as np 
from lmfit import GaussianModel 
data =np.loadtxt('mock.txt') 
my_x=data[:,0] 
my_y=data[:,1] 

model = (GaussianModel(prefix='p1_') + 
      GaussianModel(prefix='p2_') + 
      GaussianModel(prefix='p3_')) 

params = model.make_params(p1_amplitude=100, p1_sigma=2, p1_center=2262, 
          p2_amplitude=100, p2_sigma=2, p2_center=2269, 
          p3_amplitude=100, p3_sigma=2, p3_center=2276, 
         ) 

# set boundaries on the Gaussian Centers: 
params['p1_center'].min = 2260 
params['p1_center'].max = 2264 

params['p2_center'].min = 2267 
params['p2_center'].max = 2273 

params['p3_center'].min = 2274 
params['p3_center'].max = 2279 

# or you could just fix one of the centroids like this: 
params['p3_center'].vary = False 

# if needed, you could force all the sigmas to be the same value 
# or related by simple mathematical expressions 
params['p2_sigma'].expr = 'p1_sigma' 
params['p3_sigma'].expr = '2*p1_sigma' 

# fit this model to data: 
result = model.fit(my_y, params, x=my_x) 

# print results 
print(result.fit_report()) 

# evaluate individual gaussian components: 
peaks = model.eval_components(params=result.params, x=my_x) 

# plot results: 
plt.plot(my_x, my_y, label='data') 
plt.plot(my_x, result.best_fit, label='best fit') 
plt.plot(my_x, peaks['p1_']) 
plt.plot(my_x, peaks['p2_']) 
plt.plot(my_x, peaks['p3_']) 
plt.show() 
+0

'scipy.curve_fit'は現在のバージョンと同様に境界を知っています。こちらをご覧ください:https://stackoverflow.com/questions/16760788/python-curve-fit-library-that-allows-me-to-assign-bounds-to-parameters – NichtJens

0

センターに対して固定値の3つの独立した関数を定義する必要があります。次に、これらの関数の合計関数を残りのパラメータだけに適合させます。

簡潔に言えば、はmu秒ではなく、A秒とsigma秒の間になるはずです。 muは定数でなければなりません。これを行うための

些細な(しかし非常に一般的ではない)方法は、次のとおりです。

def trimodal_gauss(x, sigma1, A1, sigma2, A2, sigma3, A3): 
    mu1 = 1234 # put your mu's here 
    mu2 = 2345 
    mu3 = 3456 
    g1 = gauss(x, mu1, sigma1, A1) 
    g2 = gauss(x, mu2, sigma2, A2) 
    g3 = gauss(x, mu3, sigma3, A3) 
    return g1 + g2 + g3 

この1から3要するtrimodal_gauss機能のために、「発電機」でアイデアを一般化することができますmu(あるいはnを?)他のパラメータの関数を作成します。これと同じように:あなたはlmfitモジュール(https://github.com/lmfit/lmfit-py)を使用している場合

def make_trimodal_gauss(mu1, mu2, mu3): 
    def result_function(x, sigma1, A1, sigma2, A2, sigma3, A3): 
     g1 = gauss(x, mu1, sigma1, A1) 
     g2 = gauss(x, mu2, sigma2, A2) 
     g3 = gauss(x, mu3, sigma3, A3) 
     return g1 + g2 + g3 
    return result_function 


mu1 = 1234 # put your mu's here 
mu2 = 2345 
mu3 = 3456 

trimodal_gauss = make_trimodal_gauss(mu1, mu2, mu3) 

#usage like this: trimodal_gauss(x, sigma1, A1, sigma2, A2, sigma3, A3) 
+0

ありがとう。 muが関数の一部でない場合、ガウス関数が重心に収まるようにするにはどうすればよいでしょうか? – user7852656

+0

私はそれを私の答えにするために一つの方法を加えました。 – NichtJens

関連する問題