From 238e18a5ce087c3b2940722bda86b39a95a44065 Mon Sep 17 00:00:00 2001 From: Erich Eckner Date: Tue, 29 Mar 2016 15:00:11 +0200 Subject: Gaußfit eingebaut MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- epost.lpi | 6 +- epost.lpr | 11 +++ epost.lps | 223 ++++++++++++++++++++++++----------------------- epostunit.pas | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- gauszFit.inc | 17 ++++ typenunit.pas | 66 ++++++++++++++ werteunit.pas | 179 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 657 insertions(+), 117 deletions(-) create mode 100644 gauszFit.inc diff --git a/epost.lpi b/epost.lpi index 89d94c9..4f8aa37 100644 --- a/epost.lpi +++ b/epost.lpi @@ -39,7 +39,7 @@ - + @@ -72,6 +72,10 @@ + + + + diff --git a/epost.lpr b/epost.lpr index ab04b20..93fed13 100644 --- a/epost.lpr +++ b/epost.lpr @@ -284,6 +284,17 @@ begin aufraeumen; halt(1); end; + if startetMit('Fitte Gauße an ',s) then begin + i:=findeWerte(s,nil,@wertes,@Konturen,false); + if i<0 then begin + aufraeumen; + halt(1); + end; + if wertes[i].fitteGausze(syntaxtest,inf,maxthreads) then + continue; + aufraeumen; + halt(1); + end; if startetMit('Zeitfrequenzanalyse ',s) then begin j:=findeWerte(erstesArgument(s),nil,@wertes,@Konturen,false); if j<0 then begin diff --git a/epost.lps b/epost.lps index e90a86d..69c0fb7 100644 --- a/epost.lps +++ b/epost.lps @@ -3,13 +3,12 @@ - + - - - + + @@ -23,11 +22,9 @@ - - - - + + @@ -41,10 +38,9 @@ - - - - + + + @@ -52,8 +48,8 @@ - - + + @@ -62,7 +58,7 @@ - + @@ -70,232 +66,241 @@ - + + + + + + + + + - - - + + + - - - - - - - - + - - - + + + + + + + + + + + - + - - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - + - + - + + - + - + - - + + - + - + - - + + - + - + - + - + - + - - + + - - + + - - + + - - + + - + - + - - + + - - + + diff --git a/epostunit.pas b/epostunit.pas index dda146b..42c7151 100644 --- a/epostunit.pas +++ b/epostunit.pas @@ -142,6 +142,8 @@ type procedure ermittleMinMaxDichten(st: boolean; threads,xmin,xmax,tmin,tmax: longint; symmetrisch: boolean); overload; procedure gleicheMinMaxDichtenAn(st: boolean; f: tMyStringlist; symmetrisch: boolean); function fft(threads: longint; senkrecht,invers: boolean; const vor,nach: tFFTDatenordnung; fen: tFenster; out pvFehler: extended; Warn: tWarnstufe): boolean; overload; + procedure initFuerGauszFit(st: boolean; daten: tWerte; senkrecht: boolean; adLaenge: longint; adStart,adStop: extended); + function fitteGausze(st: boolean; f: tMyStringlist; threads: longint): boolean; function berechneZeitfrequenzanalyse(st: boolean; f: tMyStringlist; threads: longint; quelle: tWerte; Warn: tWarnstufe): boolean; function berechneVerzerrung(st: boolean; f: tMyStringlist; threads: longint; quelle: tWerte; Warn: tWarnstufe): boolean; function berechneIntegral(st: boolean; f: tMyStringlist; threads: longint; quelle: tWerte): boolean; @@ -278,6 +280,16 @@ type destructor destroy; override; procedure stExecute; override; end; + tGauszFitThread = class(tLogThread) + qu: tWerte; + ampl,br,posi,ueberl,hint: pTLLWerteExtended; + vo,bi: longint; + senkr: boolean; + fenBr,maxBr,maxVersch: extended; + posiMitten: tExtendedArray; + constructor create(daten,amplituden,breiten,positionen,ueberlappe,hintergruende: tWerte; von,bis: longint; senkrecht: boolean; fensterBreite,maxBreite,maxVerschiebung: extended; positionsMitten: tExtendedArray); + procedure stExecute; override; + end; tKorrelThread = class(tLogThread) wl: tWavelet; xMi,xMa: longint; @@ -2049,11 +2061,11 @@ begin (Transformationen as tAgglomeration).nullposition:=exprtofloat(st,s); continue; end; - if s='horizontal' then begin + if s='waagerecht' then begin (Transformationen as tAgglomeration).horizontal:=true; continue; end; - if s='vertikal' then begin + if s='senkrecht' then begin (Transformationen as tAgglomeration).horizontal:=true; continue; end; @@ -2626,6 +2638,201 @@ begin gibAus('Alle FFTThreads fertig!',1); end; +procedure tWerte.initFuerGauszFit(st: boolean; daten: tWerte; senkrecht: boolean; adLaenge: longint; adStart,adStop: extended); +begin + Transformationen:=tFitTransformation.create(daten.Transformationen,senkrecht,adLaenge,adStart,adStop); + _xsteps:=Transformationen.xsteps; + _tsiz:=Transformationen.tsiz; + Genauigkeit:=gExtended; + if not st then + eWerte.holeRam(3); +end; + +function tWerte.fitteGausze(st: boolean; f: tMyStringlist; threads: longint): boolean; +var + Zeit: extended; + senkrecht,fertig: boolean; + s: string; + i,iterDim: longint; + ampl,br,posi,ueberl,hint: tWerte; + maxBreite,maxVerschiebung,fensterBreite: extended; + posiMitten: tExtendedArray; + gauszFitThreads: array of tGauszFitThread; +begin + result:=false; + Zeit:=now; + if not st then + gibAus('Gauße fitten ...',3); + ampl:=nil; + br:=nil; + posi:=nil; + ueberl:=nil; + hint:=nil; + senkrecht:=true; + maxBreite:=-1; + maxVerschiebung:=-1; + fensterBreite:=-1; + setlength(posiMitten,0); + repeat + if not f.metaReadln(s,true) then begin + gibAus('Unerwartetes Dateiende!',3); + exit; + end; + if s='Ende' then break; + if s='senkrecht' then begin + senkrecht:=true; + continue; + end; + if s='waagerecht' then begin + senkrecht:=false; + continue; + end; + if startetMit('Amplituden:',s) then begin + i:=findeWerte(s,f,wertes,konturen,true); + if i<0 then + exit; + if assigned(ampl) then begin + gibAus('Habe bereits ein Ziel für die Amplituden beim Fitten eines Gaußes!',3); + exit; + end; + ampl:=wertes^[i]; + continue; + end; + if startetMit('Breiten:',s) then begin + i:=findeWerte(s,f,wertes,konturen,true); + if i<0 then + exit; + if assigned(br) then begin + gibAus('Habe bereits ein Ziel für die Breiten beim Fitten eines Gaußes!',3); + exit; + end; + br:=wertes^[i]; + continue; + end; + if startetMit('Positionen:',s) then begin + i:=findeWerte(s,f,wertes,konturen,true); + if i<0 then + exit; + if assigned(posi) then begin + gibAus('Habe bereits ein Ziel für die Positionen beim Fitten eines Gaußes!',3); + exit; + end; + posi:=wertes^[i]; + continue; + end; + if startetMit('Überlapp:',s) then begin + i:=findeWerte(s,f,wertes,konturen,true); + if i<0 then + exit; + if assigned(ueberl) then begin + gibAus('Habe bereits ein Ziel für den Überlapp beim Fitten eines Gaußes!',3); + exit; + end; + ueberl:=wertes^[i]; + continue; + end; + if startetMit('Hintergrund:',s) then begin + i:=findeWerte(s,f,wertes,konturen,true); + if i<0 then + exit; + if assigned(hint) then begin + gibAus('Habe bereits ein Ziel für den Hintergrund beim Fitten eines Gaußes!',3); + exit; + end; + hint:=wertes^[i]; + continue; + end; + if startetMit('Maximalverschiebung:',s) then begin + maxVerschiebung:=kont2diskFak(senkrecht,exprtofloat(st,s)); + continue; + end; + if startetMit('Maximalbreite:',s) then begin + maxBreite:=kont2diskFak(senkrecht,exprtofloat(st,s)); + continue; + end; + if startetMit('Fensterbreite:',s) then begin + fensterBreite:=kont2diskFak(senkrecht,exprtofloat(st,s)); + continue; + end; + if startetMit('Positionsbereichsmitten:',s) then begin + while s<>'' do + fuegeSortiertHinzu(kont2disk(senkrecht,exprToFloat(st,erstesArgument(s))),posiMitten); + continue; + end; + gibAus('Verstehe Option '''+s+''' nicht beim Fitten eines Gaußes!',3); + exit; + until false; + + if (2*maxVerschiebung>fensterBreite) or ((maxVerschiebung<0) and (fensterBreite>0)) then + maxVerschiebung:=fensterBreite/2; + + if length(posiMitten)=0 then begin + gibAus('Es sind keine Gauße zu fitten! Was soll das?',3); + exit; + end; + + if not (assigned(ampl) or assigned(br) or assigned(posi) or assigned(ueberl) or assigned(hint)) then begin + gibAus('Es sind keine Parameter des Gaußes zu speichern! Was soll das?',3); + exit; + end; + + if assigned(ampl) then + ampl.initFuerGauszFit(st,self,senkrecht,length(posiMitten),posiMitten[0],posiMitten[length(posiMitten)-1]); + if assigned(br) then + br.initFuerGauszFit(st,self,senkrecht,length(posiMitten),posiMitten[0],posiMitten[length(posiMitten)-1]); + if assigned(posi) then + posi.initFuerGauszFit(st,self,senkrecht,length(posiMitten),posiMitten[0],posiMitten[length(posiMitten)-1]); + if assigned(ueberl) then + ueberl.initFuerGauszFit(st,self,senkrecht,length(posiMitten),posiMitten[0],posiMitten[length(posiMitten)-1]); + if assigned(hint) then + hint.initFuerGauszFit(st,self,senkrecht,length(posiMitten),posiMitten[0],posiMitten[length(posiMitten)-1]); + + if senkrecht then + iterDim:=_xsteps + else + iterDim:=_tsiz; + + if threads > iterDim then + threads:=iterDim; + + if st then begin + result:=true; + exit; + end; + + setlength(gauszFitThreads,threads); + for i:=0 to threads-1 do + gauszFitThreads[i]:= + tGauszFitThread.create( + self, + ampl, + br, + posi, + ueberl, + hint, + round(i*iterDim/threads), + round((i+1)*iterDim/threads)-1, + senkrecht, + fensterBreite, + maxBreite, + maxVerschiebung, + posiMitten + ); + + repeat + sleep(10); + fertig:=true; + for i:=0 to threads-1 do + fertig:=fertig and gauszFitThreads[i].fertig; + until fertig; + + for i:=0 to threads-1 do + gauszFitThreads[i].free; + + gibAus('... fertig '+timetostr(now-Zeit),3); + result:=true; +end; + function tWerte.berechneZeitfrequenzanalyse(st: boolean; f: tMyStringlist; threads: longint; quelle: tWerte; Warn: tWarnstufe): boolean; var i,tmin,tmax,qlen: longint; @@ -3003,7 +3210,7 @@ begin continue; end; if startetMit('Richtung:',s) then begin - if s='horizontal' then begin + if s='waagerecht' then begin rtg:=irHorizontal; continue; end; @@ -3792,15 +3999,15 @@ begin params:=trim(params); if startetMit('integriere ',params) then begin - if startetMit('horizontal',params) then b1:=true - else if startetMit('vertikal',params) then b1:=false + if startetMit('waagerecht',params) then b1:=true + else if startetMit('senkrecht',params) then b1:=false else exit; if st then begin result:=true; exit; end; - if b1 then s:='horizontal' - else s:='vertikal'; + if b1 then s:='waagerecht' + else s:='senkrecht'; gibAus('... schreibe in '''+params+''', integriere '+s,3); if pos(' ',params)>0 then begin @@ -4855,6 +5062,57 @@ begin fertig:=true; end; +// tGauszFitThread ************************************************************* + +constructor tGauszFitThread.create(daten,amplituden,breiten,positionen,ueberlappe,hintergruende: tWerte; von,bis: longint; senkrecht: boolean; fensterBreite,maxBreite,maxVerschiebung: extended; positionsMitten: tExtendedArray); +begin + inherited create; + qu:=daten; + if assigned(amplituden) then + ampl:=@amplituden.eWerte + else + ampl:=nil; + if assigned(breiten) then + br:=@breiten.eWerte + else + br:=nil; + if assigned(positionen) then + posi:=@positionen.eWerte + else + posi:=nil; + if assigned(ueberlappe) then + ueberl:=@ueberlappe.eWerte + else + ueberl:=nil; + if assigned(hintergruende) then + hint:=@hintergruende.eWerte + else + hint:=nil; + vo:=von; + bi:=bis; + senkr:=senkrecht; + fenBr:=fensterBreite; + maxBr:=maxBreite; + maxVersch:=maxVerschiebung; + posiMitten:=positionsMitten; + gibAus('GaußFitThread kreiert: '+inttostr(von)+'-'+inttostr(bis),1); + suspended:=false; +end; + +procedure tGauszFitThread.stExecute; +begin + gibAus('GaußFitThread gestartet ...',1); + case qu.Genauigkeit of + gSingle: + qu.sWerte.gauszFit(ampl,br,posi,ueberl,hint,vo,bi,senkr,fenBr,maxBr,maxVersch,posiMitten); + gDouble: + qu.dWerte.gauszFit(ampl,br,posi,ueberl,hint,vo,bi,senkr,fenBr,maxBr,maxVersch,posiMitten); + gExtended: + qu.eWerte.gauszFit(ampl,br,posi,ueberl,hint,vo,bi,senkr,fenBr,maxBr,maxVersch,posiMitten); + end{of case}; + gibAus('... und fertig',1); +end; + // tKorrelThread *************************************************************** constructor tKorrelThread.create(quelle,ziel: tWerte; xMin,xMax: longint; wavelet: tWavelet); diff --git a/gauszFit.inc b/gauszFit.inc new file mode 100644 index 0000000..e90392f --- /dev/null +++ b/gauszFit.inc @@ -0,0 +1,17 @@ +{$IFDEF gauszFitBerechneWerte} + fehlers[nParams]:=0; + for ii:=0 to length(parameter[nParams,true])-1 do + parameter[nParams,true,ii]:=0; + + for ii:=wiMin to wiMax do begin + t0:=ii-parameter[nParams,false,0]; + t1:=exp( - sqr(t0 * parameter[nParams,false,1]) ); + t2:=parameter[nParams,false,2] * t1; + t3:=werte[offset+qpSchritt*ii] - t2 - parameter[nParams,false,3]; + fehlers[nParams]:=fehlers[nParams] + sqr(t3); + parameter[nParams,true,0]:=parameter[nParams,true,0] - t3 * t2 * 2 * t0 * sqr(parameter[nParams,false,1]); + parameter[nParams,true,1]:=parameter[nParams,true,1] + t3 * t2 * 2 * sqr(t0) * parameter[nParams,false,1]; + parameter[nParams,true,2]:=parameter[nParams,true,2] - t3 * t1; + parameter[nParams,true,3]:=parameter[nParams,true,3] - t3; + end; +{$ENDIF} diff --git a/typenunit.pas b/typenunit.pas index 5814925..6d24d16 100644 --- a/typenunit.pas +++ b/typenunit.pas @@ -397,6 +397,19 @@ type // keine Änderung der Werte(skalierung) function dumpParams: string; override; end; + tFitTransformation = class(tKoordinatenTransformation) + private + _senkrecht: boolean; + _adLaenge: longint; + _adStao: tExtPoint; + public + constructor create(daten: tTransformation; senkrecht: boolean; adLaenge: longint; adStart,adStop: extended); + procedure aktualisiereXsTs; override; + procedure aktualisiereAchsen; override; + // keine Änderung der Werte(skalierung) + function wertZuPositionAufAchse(const l: tLage; x: extended): extended; override; + function dumpParams: string; override; + end; tAgglomeration = class (tKoordinatenTransformation) private _nullposition: extended; @@ -2059,6 +2072,59 @@ begin result:='Koordinatenausschnitt: '+inttostr(gr['x','x'])+'..'+inttostr(gr['x','y'])+' x '+inttostr(gr['y','x'])+'..'+inttostr(gr['y','y']); end; +// tFitTransformation ********************************************************** + +constructor tFitTransformation.create(daten: tTransformation; senkrecht: boolean; adLaenge: longint; adStart,adStop: extended); +begin + inherited create; + wmiaExplizit:=true; // nicht sinnvoll berechenbar + _senkrecht:=senkrecht; // die Richtung, in der gefittet wurde ("andere Dimension") - also senkrecht zur übernommenen Ausdehnung + _adLaenge:=adLaenge; // Größe in der "anderen Dimension" + _adStao['x']:=adStart; // Start und + _adStao['y']:=adStop; // Stopp in der "anderen Dimension" + if (_adLaenge=1) xor (_adStao['x']=_adStao['y']) then + fehler('Die gefitteten Daten müssen genau dann eindimensional sein, wenn Start = Stopp ist. ('+inttostr(_adLaenge)+'-d vs. '+floattostr(_adStao['x'])+'..'+floattostr(_adStao['y'])+')'); + fuegeVorgaengerHinzu(daten); +end; + +procedure tFitTransformation.aktualisiereXsTs; +var + c: char; +begin + for c:='x' to 'y' do + out_xs_ts[c]:=_adLaenge+(in_xs_ts[c]-_adLaenge)*byte(_senkrecht xor (c='y')); +end; + +procedure tFitTransformation.aktualisiereAchsen; +var + c: char; +begin + for c:='x' to 'y' do begin + out_achsen[char(ord('x')+byte(_senkrecht)),c]:= + in_achsen[char(ord('x')+byte(_senkrecht)),c]; + out_achsen[char(ord('y')-byte(_senkrecht)),c]:= + _adStao[c]; + end; +end; + +function tFitTransformation.wertZuPositionAufAchse(const l: tLage; x: extended): extended; +begin + if (l in [lOben,lUnten]) xor _senkrecht then + result:=0 // keine Ausdehnung in dieser Richtung! + else + result:=vorgaenger[0].wertZuPositionAufAchse(l,x); +end; + +function tFitTransformation.dumpParams: string; +begin + result:='FitTransformation: '; + if _senkrecht then + result:=result+'vertik' + else + result:=result+'horizont'; + result:=result+'al'; +end; + // tAgglomeration ************************************************************** constructor tAgglomeration.create; diff --git a/werteunit.pas b/werteunit.pas index e35b54a..a643a7b 100644 --- a/werteunit.pas +++ b/werteunit.pas @@ -62,6 +62,7 @@ type procedure integriereSingle(qu: pTLLWerteSingle; xmi,xma,tmi,tma,xof,tof: longint; richtung: tIntegrationsRichtung); procedure integriereDouble(qu: pTLLWerteDouble; xmi,xma,tmi,tma,xof,tof: longint; richtung: tIntegrationsRichtung); procedure integriereExtended(qu: pTLLWerteDouble; xmi,xma,tmi,tma,xof,tof: longint; richtung: tIntegrationsRichtung); + procedure gauszFit(amplituden,breiten,positionen,ueberlappe,hintergruende: pTLLWerteExtended; von,bis: longint; senkrecht: boolean; fensterBreite,maxBreite,maxVerschiebung: extended; positionsMitten: tExtendedArray); end; tLLWerteSingle = specialize tLLWerte; tLLWerteDouble = specialize tLLWerte; @@ -1254,6 +1255,184 @@ begin end{of case}; end; +procedure tLLWerte.gauszFit(amplituden,breiten,positionen,ueberlappe,hintergruende: pTLLWerteExtended; von,bis: longint; senkrecht: boolean; fensterBreite,maxBreite,maxVerschiebung: extended; positionsMitten: tExtendedArray); +var + i,j,ii,zaehl, // Zähler + qpSchritt,qsSchritt, // Schrittlängen in der Quelle + zpSchritt,zdSchritt, // Schrittlängen im Ziel + pLen,offset, // Datenlänge und Offset in der Quelle + wiMin,wiMax, // momentane Fensterränder (für den Zählindex) in der Quelle + verbesserung, // <0: schlechter, 1: besser, 2: viel besser + aParams,nParams: longint; // Index der alten und neuen Parameter + parameter: array[0..1,boolean,0..3] of extended; + // dim0 nummeriert Parametersätze + // dim1: Ableitung (true) oder Werte (false) + // dim2: position, 1/breite, amplitude, hintergrund + fehlers: array[0..1] of extended; + t0,t1,t2,t3, // Zwischenergebnisse + qdrSumm, // Quadratesumme im betrachteten Fenster + pMi,pMa, // Achsenenden in Datenrichtung + schrittFaktor: extended; + ignBr,ignVersch: boolean; // Breite/Verschiebung am Anschlag! +begin + if senkrecht then begin + qpSchritt:=params.xsteps; // Schritt in der Quelle parallel zur Fit-Richtung + qsSchritt:=1; // Schritt in der Quelle senkrecht zur Fit-Richtung + zpSchritt:=params.xsteps; // Schritt im Ziel in positionsMitten-Richtung + zdSchritt:=1; // Schritt im Ziel in Daten-Richtung (= senkrecht zur Fit-Richtung) + pMi:=params.tstart; + pMa:=params.tstop; + pLen:=params.tsiz; + end + else begin + qsSchritt:=params.xsteps; + qpSchritt:=1; + zdSchritt:=length(positionsMitten); + zpSchritt:=1; + pMi:=params.xstart; + pMa:=params.xstop; + pLen:=params.xsteps; + end; + maxBreite:=1/maxBreite; + + for i:=von to bis do + for j:=0 to length(positionsMitten)-1 do begin + offset:=i*qsSchritt; + aParams:=0; + + wiMin:=0; + wiMax:=pLen-1; + if fensterBreite>0 then begin + wiMin:=max(wiMin,round(positionsMitten[j] - fensterBreite / 2)); + wiMax:=min(wiMax,round(positionsMitten[j] + fensterBreite / 2)); + end; + + qdrSumm:=0; + t0:=0; + t1:=0; + t2:=0; + schrittFaktor:=0; + for ii:=wiMin to wiMax do begin + t3:=werte[offset+qpSchritt*ii]; + t3:=abs(t3); + qdrSumm:=qdrSumm + sqr(t3); + t0:=t0 + t3; + t1:=t1 + ii*t3; + t2:=t2 + sqr(ii)*t3; + if t3>schrittFaktor then schrittFaktor:=t3; + end; + + t1:=t1/t0; + t2:=t2/t0; + + parameter[aParams,false,0]:=t1; // Erwartungswert + parameter[aParams,false,2]:=schrittFaktor; // Maximalwert + parameter[aParams,false,1]:=parameter[aParams,false,2]/t0*sqrt(pi); +// parameter[aParams,false,1]:=1/sqrt(2*(t2-sqr(t1))); // beinhalted Standardabweichung <-- schlechter!! + parameter[aParams,false,3]:=0; + + if (maxBreite>=0) and (parameter[aParams,false,1]<2*maxBreite) then + parameter[aParams,false,1]:=maxBreite*2; + + nParams:=aParams; + {$DEFINE gauszFitBerechneWerte} + {$I gauszFit.inc} // Werte + Gradienten berechnen + {$UNDEF} + + schrittFaktor:=1; + if maxVerschiebung>=0 then + schrittFaktor:=min(schrittFaktor,maxVerschiebung/max(abs(parameter[nParams,true,0]),1e-50)); + if maxBreite>=0 then + schrittFaktor:=min(schrittFaktor,abs(parameter[nParams,false,2]-maxBreite)/max(abs(parameter[nParams,true,1]),1e-50)); + + zaehl:=0; + repeat + nParams:=(aParams+1) mod length(parameter); + for ii:=0 to length(parameter[aParams,false])-1 do + parameter[nParams,false,ii]:= + parameter[aParams,false,ii] - schrittFaktor * parameter[aParams,true,ii]; // * byte(ii<3); + + ignVersch:=false; + if maxVerschiebung>0 then begin + if parameter[nParams,false,0]-positionsMitten[j] > maxVerschiebung then begin + parameter[nParams,false,0]:=positionsMitten[j] + maxVerschiebung; + ignVersch:=true; + end; + if positionsMitten[j]-parameter[nParams,false,0] > maxVerschiebung then begin + parameter[nParams,false,0]:=positionsMitten[j] - maxVerschiebung; + ignVersch:=true; + end; + end; + + ignBr:=false; + if maxBreite>0 then + if parameter[nParams,false,1] < maxBreite then begin + parameter[nParams,false,1]:=maxBreite; + ignBr:=true; + end; + + {$DEFINE gauszFitBerechneWerte} + {$I gauszFit.inc} // Werte + Gradienten berechnen + {$UNDEF} + + if fehlers[aParams]>2*fehlers[nParams] then begin + verbesserung:=2; + schrittFaktor:=schrittFaktor * 2; + aParams:=nParams; + end + else if fehlers[aParams]>fehlers[nParams] then begin + verbesserung:=1; + schrittFaktor:=schrittFaktor * 1.3; + aParams:=nParams; + end + else begin + if verbesserung>0 then + verbesserung:=-1 + else + dec(verbesserung); + schrittFaktor:=schrittFaktor * 0.5; + end; + + if schrittFaktor<1e-50 then + fehler('Sehr kleiner Schrittfaktor ('+floattostr(schrittFaktor)+') beim Fitten!'); + + inc(zaehl); + {$IFDEF gauszFitStatus} + if (zaehl mod 10000)=0 then + gibAus( + floattostr(fehlers[aParams])+' '+ + floattostr(qdrSumm)+' '+ + inttostr(byte((verbesserung<-10) or (fehlers[aParams]*100=100000) or (verbesserung<-10) or (fehlers[aParams]*10