2012-11-08 11 views
8

Ich habe eine Reihe von Frequenzdaten mit Peaks, auf die ich eine Gauß-Kurve anpassen muss und dann die volle Breite halbmaximal aus. Der FWHM-Teil, den ich tun kann, habe ich bereits einen Code dafür, aber ich habe Probleme, Code zu schreiben, um den Gaußschen zu passen.Wie wird ein Gaussian an Daten in Matlab/Oktave angepasst?

Kennt irgendjemand irgendwelche Funktionen, die das für mich tun oder mir in die richtige Richtung zeigen könnten? (Ich kann die kleinsten Quadrate für Linien und Polynome verwenden, aber ich kann nicht für Gaussians arbeiten)

Es wäre auch hilfreich, wenn es sowohl mit Octave als auch mit Matlab kompatibel wäre, da ich Octave im Moment habe, aber nicht bekomme bis nächste Woche keinen Zugang zu Matlab.

Jede Hilfe würde sehr geschätzt werden!

+0

Haben Sie eine einzelne Spitze haben (nur 1 Gaussian)? Oder mehrere Spitzen (mehrere, überlappende Gassians)? –

+0

Es ist nur ein einzelner Peak pro Datei. – user1806676

+1

Wenn es sich nur um einen Peak handelt, nehmen Sie den Mittelwert und den Standard-Dev der Zahlen und definieren Sie die normale Verteilung Ihrer Stichprobe. Hast du das probiert? Wenn Sie die Toolbox "stats" verwenden, verwenden Sie andernfalls "normfit()". – Justin

Antwort

19

eine einzelne 1D Gauß-Montage ist direkt eine nicht-lineare Anpassung Problem. Sie werden fertige Implementierungen here finden oder here oder here for 2D oder here (wenn Sie die Statistik-Toolbox haben) (haben Sie schon gehört von Google? :)

Wie auch immer, es könnte eine einfachere Lösung sein. Wenn Sie wissen sicher, y Ihre Daten gut beschrieben durch eine Gauß'sche wird, und ist einigermaßen gut verteilt über den gesamten x -range, können Sie das Problem (diese sind Gleichungen, keine Aussagen) linearisieren:

y = 1/(σ·√(2π)) · exp(-½ ((x-μ)/σ)²) 
ln y = ln(1/(σ·√(2π))) - ½ ((x-μ)/σ)² 
    = Px² + Qx + R   

wo die Substitutionen

P = -1/(2σ²) 
Q = +2μ/(2σ²)  
R = ln(1/(σ·√(2π))) - ½(μ/σ)² 

wurden gemacht. Nun lösen für das lineare System Ax=b mit (diese sind Matlab-Anweisungen):

% design matrix for least squares fit 
xdata = xdata(:); 
A = [xdata.^2, xdata, ones(size(xdata))]; 

% log of your data 
b = log(y(:));     

% least-squares solution for x 
x = A\b;      

Der Vektor x Sie auf diese Weise gefunden werden gleich

x == [P Q R] 

die Sie dann Reverse-Engineering müssen die finden bedeuten μ und die Standardabweichung σ:

mu = -x(2)/x(1)/2; 
sigma = sqrt(-1/2/x(1)); 

, die Sie mit x(3) == R Cross-Check können (es sollte nur kleine Unterschiede).

+0

Vielen Dank. Ich konnte nur den ersten der Links über Google finden und das funktionierte nicht mit meinen Daten, der zweite funktioniert jedoch ein Leckerbissen. Auch danke für die Erklärung/Gleichungen. : D – user1806676

+0

@ user1806676: Ich habe den linearisierten Ansatz nicht versucht, aber zumindest ist die Mathematik korrekt. Sie sollten dort etwas experimentieren und validieren. –

+0

Versucht den linearisierten Ansatz. Funktioniert gut. –

2

Vielleicht hat dies das, was Sie suchen? Nicht sicher Kompatibilität: http://www.mathworks.com/matlabcentral/fileexchange/11733-gaussian-curve-fit

Von seiner Dokumentation:

[sigma,mu,A]=mygaussfit(x,y) 
[sigma,mu,A]=mygaussfit(x,y,h) 

this function is doing fit to the function 
y=A * exp(-(x-mu)^2/(2*sigma^2)) 

the fitting is been done by a polyfit 
the lan of the data. 

h is the threshold which is the fraction 
from the maximum y height that the data 
is been taken from. 
h should be a number between 0-1. 
if h have not been taken it is set to be 0.2 
as default. 
+0

Besser als Kommentar geeignet, nicht? –

+0

Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz zur Verfügung zu stellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. - [Aus Bewertung] (/ review/low-quality-posts/13114204) –

+1

@ScottHoltzman Danke für den Kopf, ich habe die entsprechende Beschreibung eingefügt. –

1

Ich hatte ähnliches Problem. das war das erste ergebnis bei google, und einige der hier verlinkten scripts machten mein matlab zum crash.

schließlich fand ich here, dass Matlab in Fit-Funktion gebaut hat, die Gaussians auch passen kann.

es so aussehen:

>> v=-30:30; 
>> fit(v', exp(-v.^2)', 'gauss1') 

ans = 

    General model Gauss1: 
    ans(x) = a1*exp(-((x-b1)/c1)^2) 
    Coefficients (with 95% confidence bounds): 
     a1 =   1 (1, 1) 
     b1 = -8.489e-17 (-3.638e-12, 3.638e-12) 
     c1 =   1 (1, 1) 
+1

Beachten Sie, dass 'fit' nicht eingebaut ist; Es ist Teil der Toolbox zur Kurvenanpassung –

0

Ich fand, dass der MATLAB "fit" -Funktion war langsam, und "lsqcurvefit" mit einer Inline-Gauß-Funktion verwendet.Dies ist für die Anpassung einer Gaußschen FUNKTION. Wenn Sie nur Daten in eine Normalverteilung einpassen möchten, verwenden Sie "normfit".

prüfen es

% % Generate synthetic data (for example) % % % 

    nPoints = 200; binSize = 1/nPoints ; 
    fauxMean = 47 ;fauxStd = 8; 
    faux = fauxStd.*randn(1,nPoints) + fauxMean; % REPLACE WITH YOUR ACTUAL DATA 
    xaxis = 1:length(faux) ;fauxData = histc(faux,xaxis); 

    yourData = fauxData; % replace with your actual distribution 
    xAxis = 1:length(yourData) ; 

    gausFun = @(hms,x) hms(1) .* exp (-(x-hms(2)).^2 ./ (2*hms(3)^2)) ; % Gaussian FUNCTION 

% % Provide estimates for initial conditions (for lsqcurvefit) % % 

    height_est = max(fauxData)*rand ; mean_est = fauxMean*rand; std_est=fauxStd*rand; 
    x0 = [height_est;mean_est; std_est]; % parameters need to be in a single variable 

    options=optimset('Display','off'); % avoid pesky messages from lsqcurvefit (optional) 
    [params]=lsqcurvefit(gausFun,x0,xAxis,yourData,[],[],options); % meat and potatoes 

    lsq_mean = params(2); lsq_std = params(3) ; % what you want 

% % % Plot data with fit % % % 
    myFit = gausFun(params,xAxis); 
    figure;hold on;plot(xAxis,yourData./sum(yourData),'k'); 
    plot(xAxis,myFit./sum(myFit),'r','linewidth',3) % normalization optional 
    xlabel('Value');ylabel('Probability');legend('Data','Fit')