diff options
author | Erich Eckner <git@eckner.net> | 2016-03-29 15:00:11 +0200 |
---|---|---|
committer | Erich Eckner <git@eckner.net> | 2016-03-30 16:08:21 +0200 |
commit | 238e18a5ce087c3b2940722bda86b39a95a44065 (patch) | |
tree | 1520af6e6ae342de306905e2d64f01c1e7cbfb6e | |
parent | da9fb8d996bbf50058d6ca40137fcc9eb14b4f82 (diff) | |
download | epost-238e18a5ce087c3b2940722bda86b39a95a44065.tar.xz |
Gaußfit eingebaut
-rw-r--r-- | epost.lpi | 6 | ||||
-rw-r--r-- | epost.lpr | 11 | ||||
-rw-r--r-- | epost.lps | 223 | ||||
-rw-r--r-- | epostunit.pas | 272 | ||||
-rw-r--r-- | gauszFit.inc | 17 | ||||
-rw-r--r-- | typenunit.pas | 66 | ||||
-rw-r--r-- | werteunit.pas | 179 |
7 files changed, 657 insertions, 117 deletions
@@ -39,7 +39,7 @@ <PackageName Value="LazUtils"/> </Item1> </RequiredPackages> - <Units Count="8"> + <Units Count="9"> <Unit0> <Filename Value="epost.lpr"/> <IsPartOfProject Value="True"/> @@ -72,6 +72,10 @@ <Filename Value="../units/fftunit.inc"/> <IsPartOfProject Value="True"/> </Unit7> + <Unit8> + <Filename Value="gauszFit.inc"/> + <IsPartOfProject Value="True"/> + </Unit8> </Units> </ProjectOptions> <CompilerOptions> @@ -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 @@ -3,13 +3,12 @@ <ProjectSession> <Version Value="9"/> <BuildModes Active="Default"/> - <Units Count="23"> + <Units Count="24"> <Unit0> <Filename Value="epost.lpr"/> <IsPartOfProject Value="True"/> - <TopLine Value="80"/> - <CursorPos X="14" Y="65"/> - <FoldState Value=" T0icW39123111221]65151[84313[4421[Q4121[85]a9"/> + <TopLine Value="55"/> + <CursorPos Y="81"/> <UsageCount Value="202"/> <Loaded Value="True"/> </Unit0> @@ -23,11 +22,9 @@ <Unit2> <Filename Value="epostunit.pas"/> <IsPartOfProject Value="True"/> - <IsVisibleTab Value="True"/> <EditorIndex Value="1"/> - <TopLine Value="2772"/> - <CursorPos Y="2792"/> - <FoldState Value=" T0/Cm$0C1~"/> + <TopLine Value="2748"/> + <CursorPos X="9" Y="2783"/> <UsageCount Value="201"/> <Loaded Value="True"/> </Unit2> @@ -41,10 +38,9 @@ <Unit4> <Filename Value="werteunit.pas"/> <IsPartOfProject Value="True"/> - <EditorIndex Value="4"/> - <TopLine Value="619"/> - <CursorPos X="29" Y="627"/> - <FoldState Value=" T0pekl05121U1S"/> + <IsVisibleTab Value="True"/> + <EditorIndex Value="3"/> + <FoldState Value=" T0pfkl05121U1V"/> <UsageCount Value="200"/> <Loaded Value="True"/> </Unit4> @@ -52,8 +48,8 @@ <Filename Value="typenunit.pas"/> <IsPartOfProject Value="True"/> <EditorIndex Value="5"/> - <TopLine Value="2329"/> - <CursorPos X="29" Y="2391"/> + <TopLine Value="2072"/> + <CursorPos X="98" Y="2086"/> <UsageCount Value="200"/> <Loaded Value="True"/> </Unit5> @@ -62,7 +58,7 @@ <IsPartOfProject Value="True"/> <EditorIndex Value="-1"/> <CursorPos X="3" Y="15"/> - <UsageCount Value="113"/> + <UsageCount Value="127"/> </Unit6> <Unit7> <Filename Value="../units/fftunit.inc"/> @@ -70,232 +66,241 @@ <EditorIndex Value="-1"/> <TopLine Value="10"/> <CursorPos X="22" Y="10"/> - <UsageCount Value="110"/> + <UsageCount Value="124"/> </Unit7> <Unit8> + <Filename Value="gauszFit.inc"/> + <IsPartOfProject Value="True"/> + <EditorIndex Value="4"/> + <CursorPos X="35" Y="10"/> + <UsageCount Value="30"/> + <Loaded Value="True"/> + </Unit8> + <Unit9> <Filename Value="../fpGUI/src/corelib/render/software/agg_scanline_storage_aa.pas"/> <EditorIndex Value="-1"/> <TopLine Value="1612"/> <CursorPos X="2" Y="1675"/> - <UsageCount Value="5"/> - </Unit8> - <Unit9> + <UsageCount Value="4"/> + </Unit9> + <Unit10> <Filename Value="../units/mystringlistunit.pas"/> <EditorIndex Value="-1"/> <TopLine Value="289"/> <CursorPos X="74" Y="300"/> - <UsageCount Value="18"/> - </Unit9> - <Unit10> - <Filename Value="../units/lowlevelunit.pas"/> - <EditorIndex Value="3"/> - <CursorPos X="32" Y="11"/> - <UsageCount Value="36"/> - <Loaded Value="True"/> + <UsageCount Value="16"/> </Unit10> <Unit11> - <Filename Value="../units/randomunit.pas"/> - <EditorIndex Value="-1"/> - <UsageCount Value="5"/> + <Filename Value="../units/lowlevelunit.pas"/> + <EditorIndex Value="2"/> + <TopLine Value="544"/> + <CursorPos Y="564"/> + <UsageCount Value="43"/> + <Loaded Value="True"/> </Unit11> <Unit12> + <Filename Value="../units/randomunit.pas"/> + <EditorIndex Value="-1"/> + <UsageCount Value="4"/> + </Unit12> + <Unit13> <Filename Value="../units/matheunit.pas"/> - <EditorIndex Value="2"/> + <EditorIndex Value="-1"/> <TopLine Value="185"/> <CursorPos X="21" Y="188"/> - <UsageCount Value="32"/> - <Loaded Value="True"/> - </Unit12> - <Unit13> + <UsageCount Value="31"/> + </Unit13> + <Unit14> <Filename Value="../units/systemunit.pas"/> <EditorIndex Value="-1"/> <TopLine Value="186"/> <CursorPos Y="161"/> - <UsageCount Value="17"/> - </Unit13> - <Unit14> + <UsageCount Value="16"/> + </Unit14> + <Unit15> <Filename Value="/usr/lib/fpc/src/rtl/inc/objpash.inc"/> <EditorIndex Value="-1"/> <TopLine Value="182"/> <CursorPos X="21" Y="202"/> - <UsageCount Value="8"/> - </Unit14> - <Unit15> + <UsageCount Value="7"/> + </Unit15> + <Unit16> <Filename Value="/usr/lib/fpc/src/rtl/unix/bunxovlh.inc"/> <EditorIndex Value="-1"/> <TopLine Value="61"/> <CursorPos X="10" Y="99"/> - <UsageCount Value="6"/> - </Unit15> - <Unit16> + <UsageCount Value="5"/> + </Unit16> + <Unit17> <Filename Value="/usr/lib/fpc/src/rtl/unix/baseunix.pp"/> <UnitName Value="BaseUnix"/> <EditorIndex Value="-1"/> <TopLine Value="61"/> - <UsageCount Value="6"/> - </Unit16> - <Unit17> + <UsageCount Value="5"/> + </Unit17> + <Unit18> <Filename Value="/usr/lib/fpc/src/rtl/unix/bunxovl.inc"/> <EditorIndex Value="-1"/> <TopLine Value="414"/> <CursorPos X="20" Y="434"/> - <UsageCount Value="6"/> - </Unit17> - <Unit18> + <UsageCount Value="5"/> + </Unit18> + <Unit19> <Filename Value="/usr/lib/fpc/src/rtl/linux/bunxsysc.inc"/> <EditorIndex Value="-1"/> <TopLine Value="16"/> - <UsageCount Value="6"/> - </Unit18> - <Unit19> + <UsageCount Value="5"/> + </Unit19> + <Unit20> <Filename Value="/usr/lib/fpc/src/rtl/unix/bunxh.inc"/> <EditorIndex Value="-1"/> <TopLine Value="74"/> <CursorPos X="15" Y="102"/> - <UsageCount Value="6"/> - </Unit19> - <Unit20> + <UsageCount Value="5"/> + </Unit20> + <Unit21> <Filename Value="/usr/lib/fpc/src/packages/fcl-image/src/fpimage.pp"/> <UnitName Value="FPimage"/> <EditorIndex Value="-1"/> <TopLine Value="10"/> <CursorPos X="3" Y="30"/> - <UsageCount Value="6"/> - </Unit20> - <Unit21> + <UsageCount Value="5"/> + </Unit21> + <Unit22> <Filename Value="../fpGUI/src/corelib/render/software/agg_basics.pas"/> <EditorIndex Value="-1"/> <TopLine Value="327"/> <CursorPos X="12" Y="347"/> - <UsageCount Value="9"/> - </Unit21> - <Unit22> + <UsageCount Value="8"/> + </Unit22> + <Unit23> <Filename Value="/usr/lib/fpc/src/rtl/objpas/classes/classesh.inc"/> <EditorIndex Value="-1"/> <TopLine Value="673"/> <CursorPos X="42" Y="705"/> - <UsageCount Value="9"/> - </Unit22> + <UsageCount Value="8"/> + </Unit23> </Units> <JumpHistory Count="30" HistoryIndex="29"> <Position1> - <Filename Value="epostunit.pas"/> - <Caret Line="89" Column="43" TopLine="69"/> + <Filename Value="gauszFit.inc"/> + <Caret Line="6" Column="19"/> </Position1> <Position2> - <Filename Value="epostunit.pas"/> - <Caret Line="1094" TopLine="1063"/> + <Filename Value="werteunit.pas"/> + <Caret Line="1274" Column="71" TopLine="1254"/> </Position2> <Position3> - <Filename Value="epostunit.pas"/> - <Caret Line="1152" Column="46" TopLine="1120"/> + <Filename Value="werteunit.pas"/> + <Caret Line="1349" Column="24" TopLine="1323"/> </Position3> <Position4> - <Filename Value="epostunit.pas"/> - <Caret Line="1156" Column="46" TopLine="1124"/> + <Filename Value="werteunit.pas"/> + <Caret Line="1367" Column="44" TopLine="1347"/> </Position4> <Position5> - <Filename Value="epostunit.pas"/> - <Caret Line="1691" Column="26" TopLine="1683"/> + <Filename Value="werteunit.pas"/> + <Caret Line="1389" Column="85" TopLine="1368"/> </Position5> <Position6> <Filename Value="werteunit.pas"/> - <Caret Line="45" Column="25" TopLine="27"/> + <Caret Line="1307" Column="25" TopLine="1281"/> </Position6> <Position7> - <Filename Value="werteunit.pas"/> - <Caret Line="631" Column="28" TopLine="382"/> + <Filename Value="epostunit.pas"/> + <Caret Line="5030" Column="13" TopLine="5015"/> </Position7> <Position8> - <Filename Value="werteunit.pas"/> - <Caret Line="645" TopLine="382"/> + <Filename Value="epostunit.pas"/> + <Caret Line="276" Column="18" TopLine="256"/> </Position8> <Position9> <Filename Value="werteunit.pas"/> - <Caret Line="641" Column="30" TopLine="602"/> + <Caret Line="1260" Column="36" TopLine="1252"/> </Position9> <Position10> <Filename Value="werteunit.pas"/> - <Caret Line="627" Column="71" TopLine="602"/> + <Caret Line="1310" Column="44" TopLine="1300"/> </Position10> <Position11> - <Filename Value="werteunit.pas"/> + <Filename Value="epostunit.pas"/> + <Caret Line="2736" Column="37" TopLine="2656"/> </Position11> <Position12> <Filename Value="epostunit.pas"/> - <Caret Line="1691" Column="26" TopLine="1683"/> + <Caret Line="116" Column="23" TopLine="97"/> </Position12> <Position13> <Filename Value="epostunit.pas"/> - <Caret Line="2797" Column="53" TopLine="2785"/> + <Caret Line="1598" Column="31" TopLine="1593"/> </Position13> <Position14> - <Filename Value="../units/matheunit.pas"/> - <Caret Line="37" Column="21" TopLine="17"/> + <Filename Value="epostunit.pas"/> + <Caret Line="1597" TopLine="1576"/> </Position14> <Position15> <Filename Value="epostunit.pas"/> - <Caret Line="2804" Column="50" TopLine="2785"/> + <Caret Line="117" Column="67" TopLine="98"/> </Position15> <Position16> <Filename Value="epostunit.pas"/> - <Caret Line="6352" Column="22" TopLine="6331"/> + <Caret Line="147" Column="25" TopLine="115"/> </Position16> <Position17> - <Filename Value="epostunit.pas"/> - <Caret Line="364" Column="24" TopLine="344"/> + <Filename Value="werteunit.pas"/> + <Caret Line="1258" Column="69" TopLine="1254"/> </Position17> <Position18> <Filename Value="epostunit.pas"/> - <Caret Line="6356" Column="13" TopLine="6343"/> + <Caret Line="5008" Column="83" TopLine="5003"/> </Position18> <Position19> <Filename Value="epostunit.pas"/> - <Caret Line="316" Column="16" TopLine="296"/> + <Caret Line="284" Column="84" TopLine="284"/> </Position19> <Position20> <Filename Value="epostunit.pas"/> - <Caret Line="371" Column="41" TopLine="338"/> + <Caret Line="2734" Column="59" TopLine="2655"/> </Position20> <Position21> <Filename Value="epostunit.pas"/> - <Caret Line="4058" Column="29" TopLine="4025"/> + <Caret Line="2729" TopLine="2676"/> </Position21> <Position22> <Filename Value="epostunit.pas"/> - <Caret Line="4059" Column="41" TopLine="4026"/> + <Caret Line="5042" Column="5" TopLine="5023"/> </Position22> <Position23> - <Filename Value="epostunit.pas"/> - <Caret Line="4060" Column="41" TopLine="4027"/> + <Filename Value="werteunit.pas"/> + <Caret Line="65" Column="23" TopLine="46"/> </Position23> <Position24> - <Filename Value="epostunit.pas"/> - <Caret Line="4061" Column="43" TopLine="4052"/> + <Filename Value="werteunit.pas"/> + <Caret Line="1404" Column="83" TopLine="1379"/> </Position24> <Position25> - <Filename Value="epostunit.pas"/> - <Caret Line="4062" Column="46" TopLine="4052"/> + <Filename Value="werteunit.pas"/> + <Caret Line="1403" Column="19" TopLine="1247"/> </Position25> <Position26> - <Filename Value="epostunit.pas"/> - <Caret Line="5618" Column="17" TopLine="5612"/> + <Filename Value="werteunit.pas"/> + <Caret Line="65" Column="78" TopLine="47"/> </Position26> <Position27> <Filename Value="epostunit.pas"/> - <Caret Line="5620" Column="26" TopLine="5627"/> + <Caret Line="277" Column="18" TopLine="258"/> </Position27> <Position28> <Filename Value="epostunit.pas"/> - <Caret Line="5724" Column="25" TopLine="5684"/> + <Caret Line="2769" Column="105" TopLine="2758"/> </Position28> <Position29> - <Filename Value="epostunit.pas"/> - <Caret Line="2640" Column="24" TopLine="2610"/> + <Filename Value="werteunit.pas"/> + <Caret Line="1394" Column="17" TopLine="1372"/> </Position29> <Position30> - <Filename Value="epostunit.pas"/> - <Caret Line="2777" TopLine="2757"/> + <Filename Value="werteunit.pas"/> + <Caret Line="1408" Column="27" TopLine="1388"/> </Position30> </JumpHistory> </ProjectSession> 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<single>; tLLWerteDouble = specialize tLLWerte<double>; @@ -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<qdrSumm)))+' '+ + inttostr(byte(ignVersch or (abs(schrittFaktor*parameter[aParams,true,0])<1)))+' '+ + inttostr(byte(ignBr or (abs(schrittFaktor*parameter[aParams,true,1]/parameter[aParams,false,1])<0.01)))+' '+ + inttostr(byte(abs(schrittFaktor*parameter[aParams,true,2]/parameter[aParams,false,2])<0.01))+' '+ + inttostr(byte(abs(schrittFaktor*parameter[aParams,true,3]/max(abs(parameter[aParams,false,3]),1e-10))<0.01))+' '+ + inttostr(verbesserung), + 3); + {$ENDIF} + + until ((zaehl>=100000) or (verbesserung<-10) or (fehlers[aParams]*10<qdrSumm)) and + (ignVersch or (abs(schrittFaktor*parameter[aParams,true,0])<1)) and + (ignBr or (abs(schrittFaktor*parameter[aParams,true,1]/parameter[aParams,false,1])<0.01)) and + (abs(schrittFaktor*parameter[aParams,true,2]/parameter[aParams,false,2])<0.01) and + (abs(schrittFaktor*parameter[aParams,true,3]/max(abs(parameter[aParams,false,3]),1e-10))<0.01); + {$IFDEF gauszFitStatus} + gibAus('',3); + {$ENDIF} + + if assigned(positionen) then + positionen^.werte[j*zpSchritt + i*zdSchritt]:=pMi+(pMa-pMi)/(pLen-1)*parameter[aParams,false,0]; + if assigned(breiten) then + breiten^.werte[j*zpSchritt + i*zdSchritt]:=(pMa-pMi)/(pLen-1)/parameter[aParams,false,1]; + if assigned(amplituden) then + amplituden^.werte[j*zpSchritt + i*zdSchritt]:=parameter[aParams,false,2]; + if assigned(hintergruende) then + hintergruende^.werte[j*zpSchritt + i*zdSchritt]:=parameter[aParams,false,3]; + if assigned(ueberlappe) then + ueberlappe^.werte[j*zpSchritt + i*zdSchritt]:=fehlers[aParams]/qdrSumm; + end; +end; + // tWavelet ******************************************************************** function tWavelet.setzeTyp(s: string): boolean; |