{ Калибровка шкалы масс 1. по двум массам; 2. (!пока нет) по многим массам. } {--------------------------------------------------------------------------- The control program for mass-spectrometer MI1201-AGM (c) Copyright Aleksandrov O.E., 2001 Molecular Physics department, USTU, Ekaterinsburg, K-2, 620002, RUSSIA phone 75-47-15 E-mail: aleks@dpt.ustu.ru Программа управления масс-спектрометром МИ1201-АГМ (c) Собственность Александрова О.Е., 2001 620002, Екатеринбург, К-2, УГТУ, Кафедра молекулярной физики тел. 75-47-15 E-mail: aleks@dpt.ustu.ru ----------------------------------------------------------------------------} unit MCAD_MI1201_Thread2; interface uses Windows, Classes, SysUtils, SyncObjs, Registry, xSystem, MITypes, MassClbr, MCAD_MI1201_TChartSeries, MCAD_MI1201_Thread_Types, MCAD_MI1201_Thread0, MCAD_MI1201_Thread01; type tCalibrationData=record M1,M2:tMass; // точные значения масс C1,C2:tCounter; // соответствующие массам значения счетчиков dC:double; // поправка к значениям счетчиков K:tMass; // коэффициент перевода счетчиков в массу end; tMArrayIndex=0..1; tMArray=array[tMArrayIndex] of tMass; tCArray=array[tMArrayIndex] of tCounter; tNCError=(nceOK, nceCommandPending, ncePeakCentering, nceCalculation, nceSetNew, nceCommandNotAvailable); tNCErrorStrs=array[tNCError] of string; tNCFlag=(fDoNotRemeasureOnMassRefine); tNCFlags=set of tNCFlag; tNCEvent=( evMassRefined, // проведено уточнение текущих масс-центров пиков evNewCalculated, // проведено вычисление новой калибровки шкалы масс evParametersChanged, // проведено изменение параметров калибровки evError, // ошибка при вычисление новой калибровки шкалы масс evPeakProcessing, evPeakProcessing_Disbalance, evPeakProcessing_End, evPeakProcessing_Error ); const cNCErrors:tNCErrorStrs=( 'OK', 'Повтор команды до завершения предыдущей', 'Ошибка при поиске центра пика', 'Ошибка при вычислении новой калибровки', 'Ошибка при установке новой калибровки', 'Команда недоступна' ); type tMsThread = class(MCAD_MI1201_Thread01.tMsThread) private prFlags:tNCFlags; prCommandPendingCounter:integer; prNewMassCalibration:tMassCalibration; // prC:tCArray; // Точные значения счетчика prM:tMArray; // Текущие значения масс prM0:tMArray; // Точные значения масс prDisbalance:tCounter; prNCError:tNCError; prPeak:integer; function GetNewK:tMass; function GetNewM0:tMass; function GetNew_dC:tMass; procedure SetError(e:tNCError); procedure SetM(i:tMArrayIndex; M:tMass); function GetM(i:tMArrayIndex):tMass; procedure SetM0(i:tMArrayIndex; M:tMass); function GetM0(i:tMArrayIndex):tMass; protected function CheckCommandPending:boolean; function CheckExCommand:boolean; function CheckExCommandPending:boolean; procedure DoRefineMasses(Sender:tObject); procedure DoRefineMass1(Sender:tObject); procedure DoRefineMass2(Sender:tObject); procedure DoCalculateNewCalibration(Sender:tObject); procedure DoSetNewCalibration(Sender:tObject); function ExecuteCmd(p:tNotifyEvent):integer; procedure ConfigSave; override; procedure ConfigRead; override; procedure CalibrationFlagsSet(AFlags:tNCFlags); function NCErrorGet:string; procedure NCNotify(ev:tNCEvent); public function PeakCenter(m:tMass):tMass; function CalibrationRefineMass(var M:tMass):boolean; function CalibrationRefineMassI(N:tMArrayIndex):boolean; function CalibrationRefineMassIX(N:tMArrayIndex):boolean; function CalibrationRefineInitialMasses:boolean; function CalibrationCalculateNew:boolean; function CalibrationSetNew:boolean; function CalibrationRefineInitialMassesX:boolean; function CalibrationCalculateNewX:boolean; function CalibrationSetNewX:boolean; function CalibrationCalculateNew_SetNew:boolean; function CalibrationRefineInitialMasses_CalculateNew:boolean; function CalibrationRefineInitialMasses_CalculateNew_SetNew:boolean; function CalibrationCalculateNew_SetNewX:boolean; function CalibrationRefineInitialMasses_CalculateNewX:boolean; function CalibrationRefineInitialMasses_CalculateNew_SetNewX:boolean; function DoRemeasure:boolean; property CalibrationError:tNCError read prNCError write SetError; property CalibrationErrorMsg:string read NCErrorGet; property CalibrationNew_K:tMass read GetNewK; property CalibrationNew_M0:tMass read GetNewM0; property CalibrationNew_dC:tMass read GetNew_dC; property CalibrationNew_C:tCArray read prC; property CalibrationDisbalance:tCounter read prDisbalance; property CalibrationCur_M[i:tMArrayIndex]:tMass read GetM write SetM; property CalibrationExact_M[i:tMArrayIndex]:tMass read GetM0 write SetM0; property CalibrationFlags:tNCFlags read prFlags write CalibrationFlagsSet; property PeakInProcessing:integer read prPeak; constructor Create(const Name:string); end; implementation constructor tMsThread.Create; begin Inherited; prNewMassCalibration.Init; end; procedure tMsThread.ConfigSave; begin Inherited; if not Assigned(Self) then Exit; if RegistryOpenKey('MassCalibration',TRUE) then begin try Registry.WriteBinaryData('M', prM, SizeOF(prM)); except end; try Registry.WriteBinaryData('M0', prM0, SizeOF(prM)); except end; try Registry.WriteBinaryData('MassCalibration', prNewMassCalibration, SizeOF(prNewMassCalibration)); prNewMassCalibration.Validate; except end; try Registry.WriteBinaryData('C', prC, SizeOF(prC)); except end; try Registry.WriteBinaryData('Disbalance', prDisbalance, SizeOF(prDisbalance)); except end; try Registry.WriteBinaryData('CalibrationFlags', prFlags, SizeOF(prFlags)); except end; end; Registry.CloseKey; end; procedure tMsThread.ConfigRead; begin Inherited; if not Assigned(Self) then Exit; if RegistryOpenKey('MassCalibration',FALSE) then begin try Registry.ReadBinaryData('M', prM, SizeOF(prM)); except end; try Registry.ReadBinaryData('M0', prM0, SizeOF(prM)); except end; try Registry.ReadBinaryData('MassCalibration', prNewMassCalibration, SizeOF(prNewMassCalibration)); except end; try Registry.ReadBinaryData('C', prC, SizeOF(prC)); except end; try Registry.ReadBinaryData('Disbalance', prDisbalance, SizeOF(prDisbalance)); except end; try Registry.ReadBinaryData('CalibrationFlags', prFlags, SizeOF(prFlags)); prFlags:=prFlags*[Low(tNCFlag)..High(tNCFlag)]; except end; end; Registry.CloseKey; end; function tMsThread.CheckCommandPending:boolean; begin if prCommandPendingCounter>0 then begin Result:=FALSE; SetError(nceCommandPending); end else begin Result:=TRUE; end; end; function tMsThread.CheckExCommand:boolean; begin Result:=IsON and IsNoError; if not Result then SetError(nceCommandNotAvailable); end; function tMsThread.CheckExCommandPending:boolean; begin Result:=CheckExCommand; if Result then Result:=CheckCommandPending; end; procedure tMsThread.SetError(e:tNCError); begin if (e=nceOK) then begin prNCError:=nceOK; NCNotify(evError); end else if (prNCError=nceOK) then begin prNCError:=e; NCNotify(evError); end; end; function tMsThread.DoRemeasure:boolean; begin Result:=not (fDoNotRemeasureOnMassRefine in CalibrationFlags) and IsON; end; function tMsThread.PeakCenter(m:tMass):tMass; begin try Result:=CenterOfPeak(m, DoRemeasure); except Result:=-1; end; end; function tMsThread.CalibrationRefineInitialMasses:boolean; var NewMs,Ms:tMArray; NewM0,M:tMass; c0:tCounter; begin Result:=CheckExCommand; if Result then begin try prPeak:=1; NCNotify(evPeakProcessing); M:=Mass; Ms:=prM; NewMs[0]:=PeakCenter(Ms[0]); Result:=(NewMs[0]<>-1); if Result then begin prPeak:=2; NCNotify(evPeakProcessing); NewMs[1]:=PeakCenter(Ms[1]); c0:=Mass2Counter(NewMs[0]); prPeak:=0; Result:=(NewMs[1]<>-1); if Result then begin NCNotify(evPeakProcessing_Disbalance); NewM0:=PeakCenter(NewMs[0]); prM:=NewMs; prDisbalance:=c0-Mass2Counter(NewM0); end else begin end; end else begin NCNotify(evPeakProcessing_Error); end; NCNotify(evMassRefined); MassX:=M; Mass:=M; prPeak:=0; NCNotify(evPeakProcessing_End); except Result:=FALSE; SetError(ncePeakCentering); end; end; end; function tMsThread.CalibrationCalculateNew:boolean; begin try prMsSp.MassCalibrationGetEx(prNewMassCalibration); Result:=prNewMassCalibration.CalculateAndSetM(prM[0],prM0[0],prM[1],prM0[1]); prC[0]:=prNewMassCalibration.Mass2Counter(prM0[0]); prC[1]:=prNewMassCalibration.Mass2Counter(prM0[1]); NCNotify(evNewCalculated); if not Result then begin SetError(nceCalculation); end; except Result:=FALSE; SetError(nceCalculation); end; end; function tMsThread.CalibrationSetNew:boolean; begin if WaitReady then begin try Result:=MassCalibrationSet(prNewMassCalibration); except Result:=FALSE; end; SetReady; end else begin Result:=FALSE; end; if not Result then SetError(nceSetNew); end; function tMsThread.GetNewK:tMass; begin Result:=prNewMassCalibration.Get_K; end; function tMsThread.GetNewM0:tMass; begin Result:=prNewMassCalibration.Get_M0; end; function tMsThread.GetNew_dC:tMass; begin Result:=prNewMassCalibration.Get_dC; end; procedure tMsThread.DoRefineMasses; begin Dec(prCommandPendingCounter); SetError(nceOK); CalibrationRefineInitialMasses; end; procedure tMsThread.DoCalculateNewCalibration; begin Dec(prCommandPendingCounter); SetError(nceOK); CalibrationCalculateNew; end; procedure tMsThread.DoSetNewCalibration; begin Dec(prCommandPendingCounter); SetError(nceOK); CalibrationSetNew; end; function tMsThread.CalibrationCalculateNew_SetNew:boolean; begin Result:=CalibrationCalculateNew and CalibrationSetNew; end; function tMsThread.CalibrationRefineInitialMasses_CalculateNew:boolean; begin Result:=CalibrationRefineInitialMasses and CalibrationCalculateNew; end; function tMsThread.CalibrationRefineInitialMasses_CalculateNew_SetNew:boolean; begin Result:=CalibrationRefineInitialMasses and CalibrationCalculateNew and CalibrationSetNew; end; function tMsThread.ExecuteCmd(p:tNotifyEvent):integer; begin Result:=ExtendedCommand(p); if Result<>-1 then Inc(prCommandPendingCounter); end; function tMsThread.CalibrationRefineInitialMassesX:boolean; begin Result:=CheckExCommandPending; if not Result then Exit; Result:=ExecuteCmd(DoRefineMasses)<>-1; end; function tMsThread.CalibrationCalculateNewX:boolean; begin Result:=CheckExCommand; if Result Then begin Result:=CheckCommandPending; if Result then begin Result:=ExecuteCmd(DoCalculateNewCalibration)<>-1; end; end else begin Result:=CalibrationCalculateNew; end; end; function tMsThread.CalibrationSetNewX:boolean; begin Result:=CheckExCommand; if Result Then begin Result:=CheckCommandPending; if Result then begin Result:=ExecuteCmd(DoSetNewCalibration)<>-1; end; end else begin Result:=CalibrationSetNew; end; end; function tMsThread.CalibrationCalculateNew_SetNewX:boolean; begin Result:=CheckExCommand; if Result Then begin Result:=CheckCommandPending; if Result then begin Result:=ExecuteCmd(DoCalculateNewCalibration)<>-1; if Result then Result:=(ExecuteCmd(DoSetNewCalibration)<>-1); end; end else begin Result:=CalibrationCalculateNew_SetNew; end; end; function tMsThread.CalibrationRefineInitialMasses_CalculateNewX:boolean; begin Result:=CheckExCommandPending; if not Result then Exit; Result:=ExecuteCmd(DoRefineMasses)<>-1; if Result then Result:=ExecuteCmd(DoCalculateNewCalibration)<>-1; end; function tMsThread.CalibrationRefineInitialMasses_CalculateNew_SetNewX:boolean; begin Result:=CheckExCommandPending; if not Result then Exit; Result:=ExecuteCmd(DoRefineMasses)<>-1; if Result then Result:=ExecuteCmd(DoCalculateNewCalibration)<>-1; if Result then Result:=ExecuteCmd(DoSetNewCalibration)<>-1; end; procedure tMsThread.SetM(i:tMArrayIndex; M:tMass); begin prM[i]:=m; end; function tMsThread.GetM(i:tMArrayIndex):tMass; begin Result:=prM[i]; end; procedure tMsThread.SetM0(i:tMArrayIndex; M:tMass); begin prM0[i]:=m; end; function tMsThread.GetM0(i:tMArrayIndex):tMass; begin Result:=prM0[i]; end; procedure tMsThread.CalibrationFlagsSet(AFlags:tNCFlags); begin prFlags:=AFlags; NCNotify(evParametersChanged); end; function tMsThread.NCErrorGet:string; begin Result:=cNCErrors[CalibrationError]; end; procedure tMsThread.NCNotify(ev:tNCEvent); begin NotifyEx(evCalibration, Byte(ev),0); end; function tMsThread.CalibrationRefineMass(var M:tMass):boolean; var NewM:tMass; begin NCNotify(evPeakProcessing); NewM:=PeakCenter(M); Result:=(NewM<>-1); if Result then begin M:=NewM; end; NCNotify(evMassRefined); NCNotify(evPeakProcessing_End); end; procedure tMsThread.DoRefineMass1; begin Dec(prCommandPendingCounter); SetError(nceOK); CalibrationRefineMassI(0); end; procedure tMsThread.DoRefineMass2; begin Dec(prCommandPendingCounter); SetError(nceOK); CalibrationRefineMassI(1); end; function tMsThread.CalibrationRefineMassIX(N:tMArrayIndex):boolean; begin Result:=CheckExCommand; if Result Then begin Result:=CheckCommandPending; if Result then begin case N of 0: Result:=ExecuteCmd(DoRefineMass1)<>-1; 1: Result:=ExecuteCmd(DoRefineMass2)<>-1; end; end; end else begin CalibrationRefineMassI(N); end; end; function tMsThread.CalibrationRefineMassI(N:tMArrayIndex):boolean; begin prPeak:=N; Result:=CalibrationRefineMass(prM[N]); end; END.