{ Эмулятор шкалы масс и сигнала } unit MassScale_Emulator; interface Uses Peak_Emulator; const cMinMassCounter=0; cMaxMassCounter=700000; cInvalidPeakNumber=-1; type tMassCounter=cMinMassCounter..cMaxMassCounter; tPeakArray=array[tPeakCount] of tPeak; tPPeakArray=^tPeakArray; tPeakNumber=cInvalidPeakNumber..High(tPeakCount); tMassScaleAndSignal=class(tObject) private Peaks:tPPeakArray; PeakCount:tPeakCount; MinMass,MaxMass:tMass; Sigma,SigmaSigma:tMass; MinAmplitude,MaxAmplitude:tSignal; Noise:tSignal; NeibourRange:tMass; procedure UnAllocate; procedure Allocate; procedure Initialize; function Size:cardinal; function FindNearestPeak(m:tMass):tPeakCount; procedure ReInit; protected public constructor Create; destructor Destroy; override; procedure SetMassRange(min,max:tMass); procedure SetPeakCount(count:tPeakCount); function Signal(Mass:tMass):tSignal; end; var MassScaleAndSignal:tMassScaleAndSignal; implementation function tMassScaleAndSignal.Size:cardinal; begin Size:=(PeakCount*SizeOf(Peaks^[0])); end; procedure tMassScaleAndSignal.UnAllocate; begin if Assigned(Peaks) and (PeakCount>0) then begin try FreeMem(Peaks,Size); finally end; end; Peaks:=NIL; end; procedure tMassScaleAndSignal.Allocate; begin Free; if (PeakCount>0) then begin try GetMem(Peaks,Size); finally end; end; end; function FindPeakPlace(m:tMass; const Peaks:tPeakArray; MaxNum:TPeakCount):TPeakCount; var i,il,ir:TPeakCount; begin il:=Low(il); ir:=MaxNum; while (ilm then begin ir:=i; end else begin il:=Succ(i); end; end; FindPeakPlace:=ir; end; procedure AddPeakAtPlace(place:TPeakCount; var Peaks:tPeakArray; MaxNum:TPeakCount); begin if Place0) then begin AssignSigma:=SigmaSigma>0; for i:=Low(i) to Pred(Low(i)+PeakCount) do begin c:=Round(xRandom(MinMass,MaxMass)); ni:=FindPeakPlace(c,Peaks^,i); AddPeakAtPlace(ni,Peaks^,i); with Peaks^[ni] do begin SetCenter(c); SetAmplitude(Round(xRandom(MinAmplitude,MaxAmplitude))); SetNoise(Noise); if AssignSigma then SetSigma(Sigma+(random(2*SigmaSigma)-SigmaSigma)) else SetSigma(Sigma); end; end; for i:=Low(i) to Pred(Low(i)+PeakCount) do begin {поиск нижней границы-соседа} if NeibourRange=M then begin Peaks^[i].SetLowNeibour(j); end else begin j:=Low(i); end; end; {поиск верхней границы-соседа} if (Peaks^[i].GetCenter)<(High(tMass)-NeibourRange)then begin M:=Peaks^[i].GetCenter+NeibourRange; end else begin M:=High(tMass); end; Peaks^[i].SetUpNeibour(i); j:=i; while (jPeaks^[Pred(PeakCount)].GetCenter) then begin FindNearestPeak:=Pred(PeakCount); end else begin FindNearestPeak:=FindPeakPlace(m, Peaks^, Pred(PeakCount)); end; end; function tMassScaleAndSignal.Signal(Mass:tMass):tSignal; var i,j:tPeakCount; x:tSignal; begin i:=FindNearestPeak(mass); x:=0; for j:=Peaks^[i].GetLowNeigbour to Peaks^[i].GetUpNeigbour do begin Inc(x,Peaks^[j].Signal(mass)); end; If Noise>0 then begin Inc(x,Round((Noise/cNoiseScale)*random)); end; Signal:=x; end; end.