2013-04-07 30 views
6

bir kozmik ışın detektörü bir enerji spektrumuna sahiptir. Spektrum, üstel bir eğri izler, ancak içinde geniş (ve belki de çok az) topaklar olacaktır. Veriler, belli ki, bir gürültü unsuru içerir.Gradyan, piton

Ben verileri düzeltmek ve daha sonra gradyan çizmek çalışıyorum. Şimdiye kadar bunu düzeltmek için scipy sline işlevini ve sonra np.gradient() öğesini kullanıyorum.

Resimde de görebileceğiniz gibi

, gradyan işlevin yöntem her bir nokta arasındaki farkları bulmak olduğunu ve çok net topaklar göstermez.

temelde pürüzsüz bir gradyan grafik gerekir. Herhangi bir yardım Muhteşem olacak!

denedim 2 spline yöntemleri:

def smooth_data(y,x,factor): 
    print "smoothing data by interpolation..." 
    xnew=np.linspace(min(x),max(x),factor*len(x)) 
    smoothy=spline(x,y,xnew) 
    return smoothy,xnew 

def smooth2_data(y,x,factor): 
    xnew=np.linspace(min(x),max(x),factor*len(x)) 
    f=interpolate.UnivariateSpline(x,y) 
    g=interpolate.interp1d(x,y) 
    return g(xnew),xnew 

düzenleme: Güvenilir sayısal türev:

def smooth_data(y,x,factor): 
    print "smoothing data by interpolation..." 
    xnew=np.linspace(min(x),max(x),factor*len(x)) 
    smoothy=spline(x,y,xnew) 
    return smoothy,xnew 

def minim(u,f,k): 
    """"functional to be minimised to find optimum u. f is original, u is approx""" 
    integral1=abs(np.gradient(u)) 
    part1=simps(integral1) 
    part2=simps(u) 
    integral2=abs(part2-f)**2. 
    part3=simps(integral2) 
    F=k*part1+part3 
    return F 


def fit(data_x,data_y,denoising,smooth_fac): 
    smy,xnew=smooth_data(data_y,data_x,smooth_fac) 
    y0,xnnew=smooth_data(smy,xnew,1./smooth_fac) 
    y0=list(y0) 
    data_y=list(data_y) 
    data_fit=fmin(minim, y0, args=(data_y,denoising), maxiter=1000, maxfun=1000) 
    return data_fit 

Ancak, sadece aynı grafiği tekrar döner!

Data, smoothed data and gradients

+0

sizin için mantıklı olurdu yumuşatma hangi düzeyde? -1 ve +1 arasındaki değerlerin çoğu ile -10 ve +1 arasında bir türev oluşturan bir? – EOL

+0

Yan Not: okuyabilir ve (http://www.python.org/dev/peps/pep-0008/) sizin "tarzı" kodlama için [PEP 8] uygulamanızı öneririz. Bu, çoğu Python programcısı (ya da iyi bir parçası) takip ettiği için kodunuzun okunmasını kolaylaştıracaktır. Atamalarda veya parametre listelerinde virgüllerden sonra '=' gibi normal boşluklar gibi küçük ayrıntılar, kodu daha okunaklı hale getirir. – EOL

cevap

8

bu yayınlanan ilginç yöntem yok: Numerical Differentiation of Noisy Data. Size probleminize güzel bir çözüm sunmalıdır. Daha fazla ayrıntı, başka bir accompanying paper verilir. Yazar ayrıca Matlab code that implements it; alternatif bir implementation in Python da mevcuttur. Eğer yivler ile yöntemi interpolasyon sürdürmeye istiyorsanız

, ben yumuşatma faktörüne scipy.interpolate.UnivariateSpline() ait s ayarlamak için öneririm.

Başka bir çözüm de işlevinizi konvolüsyon (bir Gaussian ile söyleyin) aracılığıyla düzeltmek olacaktır.

Ben büklüm yaklaşımı ile gelip eserler bazı önlemek için iddialara bağlı kağıt (spline yaklaşım benzer zorluklar muzdarip olabilir).

+0

I sayısal türev yöntemi denedik: yeni bağlanma – Lucidnonsense

+0

da bakınız 'part2 = simps (u) 'yanlış:' part2' yerine * * Her bir apsis 0 ila u integralini ihtiva eden bir dizi olmalıdır. Ardından, ihtiyaçlarınıza en uygun olanı bulmak için * katlanarak değişen * yumuşatma katsayısını denemelisiniz.Eğer x cinsinden adım büyüklüğünü dikkate alarak türevi gerçekten hesaplarsanız, 1 ile 6 arasında bir iyi bir düzeltme faktörü olmasını beklerim, çoğunlukla -1 ile + 1 arasında bulunan bir türev için - yanılıyor olabilirim; Zarfın hesaplamasının doğru olması durumunda, bu değeri yine de denemek için. – EOL

+0

Teşekkürler, bunu deneyeceğim! – Lucidnonsense

3
Bunun matematiksel geçerliliği için kefil olmaz

; EOL, atıfta bulunulacak olan LANL'den gelen kağıda benziyor. Her neyse, splev'u kullanırken SciPy’nin spline’ının yerleşik farklılaştırmasını kullanarak iyi sonuçlar aldım.

%matplotlib inline 
from matplotlib import pyplot as plt 
import numpy as np 
from scipy.interpolate import splrep, splev 

x = np.arange(0,2,0.008) 
data = np.polynomial.polynomial.polyval(x,[0,2,1,-2,-3,2.6,-0.4]) 
noise = np.random.normal(0,0.1,250) 
noisy_data = data + noise 

f = splrep(x,noisy_data,k=5,s=3) 
#plt.plot(x, data, label="raw data") 
#plt.plot(x, noise, label="noise") 
plt.plot(x, noisy_data, label="noisy data") 
plt.plot(x, splev(x,f), label="fitted") 
plt.plot(x, splev(x,f,der=1)/10, label="1st derivative") 
#plt.plot(x, splev(x,f,der=2)/100, label="2nd derivative") 
plt.hlines(0,0,2) 
plt.legend(loc=0) 
plt.show() 

matplotlib output

+0

Bu yöntemi eşit dağılmamış veriler için kullanmak mümkün mü? Ölçüm setlerimi hem X hem de Y için ekleyebilir miyim? – Spu

+0

Burada kullanılan işlevle ilgili belgeler (scipy.interpolate.splrep() '), eşit dağılmamış veriler için herhangi bir kısıtlamadan bahsetmez. Belgelere bakmanın ötesinde, kodda 'x 'değerini değiştirerek de kesinlikle kendiniz deneyebilirsiniz. Daha genel olarak, başkalarına zaman kazandırmak (ve sorunuzu cevaplamak için zaman ayırmalarını daha olası hale getirmek) amacıyla, kendi sorunuzu cevaplamak için bazı görünür çabalar kazandığınız takdir edilir. – EOL

+1

@Spu, evet! Ben sadece iki gün önce, bir FFT gerçekleştirebilmem için düzgün olmayan aralıklarla alınan örnek verilerinin kübik bir b-spline interpolatasyonunu yapmak için splrep'i kullandım. – billyjmc