/******************************************************************************** * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * * * * This software is distributed under the terms of the * * GNU Lesser General Public Licence (LGPL) version 3, * * copied verbatim in the file "LICENSE" * ********************************************************************************/ #include "CbmCheckTiming.h" #include "CbmTofDigiExp.h" #include "CbmMuchBeamTimeDigi.h" #include "FairLogger.h" #include "FairRootManager.h" #include "FairRunOnline.h" #include "TClonesArray.h" #include "TH1.h" #include "TH2.h" #include "THttpServer.h" #include using std::fixed; using std::setprecision; // ---- Default constructor ------------------------------------------- CbmCheckTiming::CbmCheckTiming() : FairTask("CbmCheckTiming") , fT0Digis{nullptr} , fStsDigis{nullptr} , fMuchDigis{nullptr} , fTofDigis{nullptr} , fRichDigis{nullptr} , fuMinTotPulserT0( 90 ) , fuMaxTotPulserT0( 100 ) { } // ---- Destructor ---------------------------------------------------- CbmCheckTiming::~CbmCheckTiming() { } // ---- Initialisation ---------------------------------------------- void CbmCheckTiming::SetParContainers() { // Load all necessary parameter containers from the runtime data base /* FairRunAna* ana = FairRunAna::Instance(); FairRuntimeDb* rtdb=ana->GetRuntimeDb(); = (*) (rtdb->getContainer("")); */ } // ---- Init ---------------------------------------------------------- InitStatus CbmCheckTiming::Init() { // Get a handle from the IO manager FairRootManager* ioman = FairRootManager::Instance(); // Get a pointer to the previous already existing data level fT0Digis = static_cast(ioman->GetObject("CbmT0Digi")); if ( ! fT0Digis ) { LOG(info) << "No TClonesArray with T0 digis found."; } fStsDigis = static_cast(ioman->GetObject("CbmStsDigi")); if ( ! fStsDigis ) { LOG(info) << "No TClonesArray with STS digis found."; } fMuchDigis = static_cast(ioman->GetObject("CbmMuchBeamTimeDigi")); if ( ! fMuchDigis ) { LOG(info) << "No TClonesArray with MUCH digis found."; } fTofDigis = static_cast(ioman->GetObject("CbmTofDigi")); if ( ! fTofDigis ) { LOG(info) << "No TClonesArray with TOF digis found."; } fRichDigis = static_cast(ioman->GetObject("CbmRichDigi")); if ( ! fRichDigis ) { LOG(info) << "No TClonesArray with RICH digis found."; } if (fCheckInterSystemOffset) CreateHistos(); return kSUCCESS; } Int_t CbmCheckTiming::CalcNrBins(Int_t offsetRange) { if (offsetRange < 1001) { fBinWidth = 5; } else if (offsetRange < 10001) { fBinWidth = 10; } else if (offsetRange < 100001) { fBinWidth = 100; } else { fBinWidth = 100; } return (offsetRange/fBinWidth *2); } void CbmCheckTiming::CreateHistos() { /// Logarithmic bining for self time comparison // Number of log bins = // 9 for the sub-unit decade // + 9 for each unit of each decade * 10 for the subdecade range // + 1 for the closing bin top edge const Int_t iNbDecadesLog = 9; const Int_t iNbStepsDecade = 9; const Int_t iNbSubStepsInStep = 1; const Int_t iNbBinsLog = iNbStepsDecade + iNbStepsDecade * iNbSubStepsInStep * iNbDecadesLog + 1; Double_t dBinsLog[iNbBinsLog]; // First fill sub-unit decade for( Int_t iSubU = 0; iSubU < iNbStepsDecade; iSubU ++ ) dBinsLog[ iSubU ] = 0.1 * ( 1 + iSubU ); std::cout << std::endl; // Then fill the main decades Double_t dSubstepSize = 1.0 / iNbSubStepsInStep; for( Int_t iDecade = 0; iDecade < iNbDecadesLog; iDecade ++) { Double_t dBase = std::pow( 10, iDecade ); Int_t iDecadeIdx = iNbStepsDecade + iDecade * iNbStepsDecade * iNbSubStepsInStep; for( Int_t iStep = 0; iStep < iNbStepsDecade; iStep++ ) { Int_t iStepIdx = iDecadeIdx + iStep * iNbSubStepsInStep; for( Int_t iSubStep = 0; iSubStep < iNbSubStepsInStep; iSubStep++ ) { dBinsLog[ iStepIdx + iSubStep ] = dBase * (1 + iStep) + dBase * dSubstepSize * iSubStep; } // for( Int_t iSubStep = 0; iSubStep < iNbSubStepsInStep; iSubStep++ ) } // for( Int_t iStep = 0; iStep < iNbStepsDecade; iStep++ ) } // for( Int_t iDecade = 0; iDecade < iNbDecadesLog; iDecade ++) dBinsLog[ iNbBinsLog - 1 ] = std::pow( 10, iNbDecadesLog ); Int_t nrOfBinsSts = CalcNrBins(fStsOffsetRange); // T0 vs. Sts fT0StsDiff = new TH1F("fT0StsDiff","T0-Sts;time diff [ns];Counts", nrOfBinsSts, -fStsOffsetRange, fStsOffsetRange); fT0StsDiffCharge = new TH2F("fT0StsDiffCharge","T0-Sts;time diff [ns]; Charge [a.u]; Counts", nrOfBinsSts, -fStsOffsetRange, fStsOffsetRange, 256, 0, 256 ); fT0StsDiffEvo = new TH2F("fT0StsDiffEvo","T0-Sts;TS; time diff [ns];Counts", 1000, 0, 10000, nrOfBinsSts, -fStsOffsetRange, fStsOffsetRange); Int_t nrOfBinsMuch = CalcNrBins(fMuchOffsetRange); // T0 vs. Much fT0MuchDiff = new TH1F("fT0MuchDiff","T0-Much;time diff [ns];Counts", nrOfBinsMuch, -fMuchOffsetRange, fMuchOffsetRange); fT0MuchDiffCharge = new TH2F("fT0MuchDiffCharge","T0-Much;time diff [ns]; Charge [a.u]; ;Counts", nrOfBinsMuch, -fMuchOffsetRange, fMuchOffsetRange, 256, 0, 256 ); fT0MuchDiffEvo = new TH2F("fT0MuchDiffEvo","T0-Much;TS; time diff [ns];Counts", 1000, 0, 10000, nrOfBinsMuch, -fMuchOffsetRange, fMuchOffsetRange); Int_t nrOfBinsTof = CalcNrBins(fTofOffsetRange); // To vs. Tof fT0TofDiff = new TH1F("fT0TofDiff","T0-Tof;time diff [ns];Counts", nrOfBinsTof, -fTofOffsetRange, fTofOffsetRange); fT0TofDiffCharge = new TH2F("fT0TofDiffCharge","T0-Tof;time diff [ns]; Charge [a.u]; ;Counts", nrOfBinsTof, -fTofOffsetRange, fTofOffsetRange, 256, 0, 256 ); fT0TofDiffEvo = new TH2F("fT0TofDiffEvo","T0-Tof;TS; time diff [ns];Counts", 1000, 0, 10000, nrOfBinsTof, -fTofOffsetRange, fTofOffsetRange); Int_t nrOfBinsRich = CalcNrBins(fRichOffsetRange); // To vs. Rich fT0RichDiff = new TH1F("fT0RichDiff","T0-Rich;time diff [ns];Counts", nrOfBinsRich, -fRichOffsetRange, fRichOffsetRange); fT0RichDiffCharge = new TH2F("fT0RichDiffCharge","T0-Rich;time diff [ns]; Charge [a.u]; ;Counts", nrOfBinsRich, -fRichOffsetRange, fRichOffsetRange, 256, 0, 256 ); fT0RichDiffEvo = new TH2F("fT0RichDiffEvo","T0-Rich;TS; time diff [ns];Counts", 1000, 0, 10000, nrOfBinsRich, -fRichOffsetRange, fRichOffsetRange); // T0 vs. Sts fT0StsDiffEvoLong = new TH2F("fT0StsDiffEvoLong","T0-Sts;TS; time diff [ns];Counts", 1800, 0, 180000, nrOfBinsSts, -fStsOffsetRange, fStsOffsetRange); // T0 vs. Much fT0MuchDiffEvoLong = new TH2F("fT0MuchDiffEvoLong","T0-Much;TS; time diff [ns];Counts", 1800, 0, 180000, nrOfBinsMuch, -fMuchOffsetRange, fMuchOffsetRange); // To vs. Tof fT0TofDiffEvoLong = new TH2F("fT0TofDiffEvoLong","T0-Tof;TS; time diff [ns];Counts", 1800, 0, 180000, nrOfBinsTof, -fTofOffsetRange, fTofOffsetRange); // To vs. Rich fT0RichDiffEvoLong = new TH2F("fT0RichDiffEvoLong","T0-Rich;TS; time diff [ns];Counts", 1800, 0, 180000, nrOfBinsRich, -fRichOffsetRange, fRichOffsetRange); // T0 vs. STS for the different DPBs fT0StsDpbDiff = new TH2F("fT0StsDpbDiff","T0-Much;DPB; time diff [ns];Counts", 2, -0.5, 1.5, nrOfBinsSts, -fStsOffsetRange, fStsOffsetRange); for( UInt_t uStsDpb = 0; uStsDpb < kuMaxNbStsDpbs; ++uStsDpb ) { fT0StsDpbDiffEvo[uStsDpb] = new TH2F( Form("fT0StsDpbDiffEvo%02u", uStsDpb), Form( "T0-STS DPB %02u;TS; time diff [ns];Counts", uStsDpb), 1800, 0, 180000, nrOfBinsSts, -fStsOffsetRange, fStsOffsetRange); fStsDpbCntsEvo[uStsDpb] = new TH1F( Form("fStsDpbCntsEvo%02u", uStsDpb), Form( "Time STS DPB %02u;TS; Hit Counts", uStsDpb), 1800, 0, 180000); } // for( UInt_t uStsDpb = 0; uStsDpb < kuMaxNbStsDpbs; ++uStsDpb ) // T0 vs. Much for the different DPBs/AFCK fT0MuchRocDiff = new TH2F("fT0MuchRocDiff","T0-Much;AFCK; time diff [ns];Counts", 20, -0.5, 19.5, nrOfBinsMuch, -fMuchOffsetRange, fMuchOffsetRange); for( UInt_t uMuchAsic = 0; uMuchAsic < kuMaxNbMuchAsics; ++uMuchAsic ) fT0MuchAsicDiffEvo[uMuchAsic] = new TH2F( Form("fT0MuchAsicDiffEvo%02u", uMuchAsic), Form( "T0-Much ASIC %02u;TS; time diff [ns];Counts", uMuchAsic), 1800, 0, 180000, nrOfBinsMuch, -fMuchOffsetRange, fMuchOffsetRange); // T0 vs. T0 fT0T0Diff = new TH1F("fT0T0Diff","T0-T0_prev;time diff [ns];Counts", iNbBinsLog - 1, dBinsLog); // sts vs. Sts fStsStsDiff = new TH1F("fStsStsDiff","Sts-Sts_prev;time diff [ns];Counts", iNbBinsLog - 1, dBinsLog); // Much vs. Much fMuchMuchDiff = new TH1F("fMuchMuchDiff","Much-Much_prev;time diff [ns];Counts", iNbBinsLog - 1, dBinsLog); // Tof vs. Tof fTofTofDiff = new TH1F("fTofTofDiff","Tof-Tof_prev;time diff [ns];Counts", iNbBinsLog - 1, dBinsLog); // Rich vs. Rich fRichRichDiff = new TH1F("fRichRichDiff","Rich-Rich_prev;time diff [ns];Counts", iNbBinsLog - 1, dBinsLog); fT0Address = new TH1F("fT0Address","T0 address;address;Counts", 1000000, 0, 1000000.); fT0Channel = new TH1F("fT0Channel","T0 channel;channel nr;Counts", 100, -0.5, 99.5); /// Register the histos in the HTTP server FairRunOnline* run = FairRunOnline::Instance(); if (run) { THttpServer* server = run->GetHttpServer(); if( nullptr != server ) { server->Register("CheckTiming", fT0StsDiff); server->Register("CheckTiming", fT0MuchDiff); server->Register("CheckTiming", fT0TofDiff); server->Register("CheckTiming", fT0RichDiff); server->Register("CheckTiming", fT0StsDiffCharge); server->Register("CheckTiming", fT0MuchDiffCharge); server->Register("CheckTiming", fT0TofDiffCharge); server->Register("CheckTiming", fT0RichDiffCharge); server->Register("CheckTiming", fT0StsDiffEvo); server->Register("CheckTiming", fT0MuchDiffEvo); server->Register("CheckTiming", fT0TofDiffEvo); server->Register("CheckTiming", fT0RichDiffEvo); server->Register("CheckTiming", fT0StsDiffEvoLong); server->Register("CheckTiming", fT0MuchDiffEvoLong); server->Register("CheckTiming", fT0TofDiffEvoLong); server->Register("CheckTiming", fT0RichDiffEvoLong); server->Register("CheckTiming", fT0T0Diff); server->Register("CheckTiming", fStsStsDiff); server->Register("CheckTiming", fMuchMuchDiff); server->Register("CheckTiming", fTofTofDiff); server->Register("CheckTiming", fRichRichDiff); server->Register("CheckTiming", fT0StsDpbDiff); for( UInt_t uStsDpb = 0; uStsDpb < kuMaxNbStsDpbs; ++uStsDpb ) server->Register("CheckTiming", fT0StsDpbDiffEvo[uStsDpb]); server->Register("CheckTiming", fT0MuchRocDiff); for( UInt_t uMuchAsic = 0; uMuchAsic < kuMaxNbMuchAsics; ++uMuchAsic ) server->Register("CheckTiming", fT0MuchAsicDiffEvo[uMuchAsic]); } } } // ---- ReInit ------------------------------------------------------- InitStatus CbmCheckTiming::ReInit() { return kSUCCESS; } // ---- Exec ---------------------------------------------------------- void CbmCheckTiming::Exec(Option_t* /*option*/) { fNrTs++; LOG(debug) << "executing TS " << fNrTs; if (fCheckTimeOrdering) CheckTimeOrder(); if (fCheckInterSystemOffset) CheckInterSystemOffset(); } void CbmCheckTiming::CheckInterSystemOffset() { LOG(debug) <<"Begin"; Int_t nrT0Digis=fT0Digis->GetEntriesFast(); Int_t nrStsDigis=fStsDigis->GetEntriesFast(); Int_t nrMuchDigis=fMuchDigis->GetEntriesFast(); Int_t nrTofDigis=fTofDigis->GetEntriesFast(); Int_t nrRichDigis=fRichDigis->GetEntriesFast(); LOG(debug) << "T0Digis: " << nrT0Digis; LOG(debug) << "StsDigis: " << nrStsDigis; LOG(debug) << "MuchDigis: " << nrMuchDigis; LOG(debug) << "TofDigis: " << nrTofDigis; LOG(debug) << "RichDigis: " << nrRichDigis; // if (nrT0Digis < 100000) { if (nrT0Digis < 1000000) { /// Re-initialize array references fPrevT0FirstDigiSts = 0.; fPrevT0FirstDigiMuch = 0.; fPrevT0FirstDigiTof = 0.; fPrevT0FirstDigiRich = 0.; for (Int_t iT0 = 0; iT0 < nrT0Digis; ++iT0) { if (iT0%1000 == 0) LOG(debug) << "Executing entry " << iT0; CbmDigi* T0Digi = static_cast(fT0Digis->At(iT0)); if( fuMinTotPulserT0 < T0Digi->GetCharge() && T0Digi->GetCharge() < fuMaxTotPulserT0 ) continue; Double_t T0Time = T0Digi->GetTime(); Int_t T0Address = T0Digi->GetAddress(); fT0Address->Fill(T0Address); // Skip pulser events. They are the only ones with charge larger than 90 if (static_cast(T0Digi)->GetCharge() > 90) continue; fT0Channel->Fill(static_cast(T0Digi)->GetCharge()); if (nrStsDigis < 1000000) fPrevT0FirstDigiSts = FillSystemOffsetHistos( fStsDigis, fT0StsDiff, fT0StsDiffCharge, fT0StsDiffEvo, fT0StsDiffEvoLong, fT0StsDpbDiff, T0Time, fStsOffsetRange, fPrevT0FirstDigiSts, kTRUE, kFALSE, kFALSE); if (nrMuchDigis < 1000000) fPrevT0FirstDigiMuch = FillSystemOffsetHistos(fMuchDigis, fT0MuchDiff, fT0MuchDiffCharge, fT0MuchDiffEvo, fT0MuchDiffEvoLong, fT0MuchRocDiff, T0Time, fMuchOffsetRange, fPrevT0FirstDigiMuch, kFALSE, kTRUE, kFALSE); if (nrTofDigis < 1000000) fPrevT0FirstDigiTof = FillSystemOffsetHistos(fTofDigis, fT0TofDiff, fT0TofDiffCharge,fT0TofDiffEvo, fT0TofDiffEvoLong, nullptr, T0Time, fTofOffsetRange, fPrevT0FirstDigiTof, kFALSE, kFALSE, kTRUE); if (nrRichDigis < 1000000) fPrevT0FirstDigiRich = FillSystemOffsetHistos(fRichDigis, fT0RichDiff, fT0RichDiffCharge,fT0RichDiffEvo, fT0RichDiffEvoLong, nullptr, T0Time, fRichOffsetRange, fPrevT0FirstDigiRich, kFALSE, kFALSE, kFALSE); } } } Int_t CbmCheckTiming::FillSystemOffsetHistos(TClonesArray* array, TH1* histo, TH2* histoCharge, TH2* histoEvo, TH2* histoEvoLong, TH2* histoAFCK, const Double_t T0Time, const Int_t offsetRange, Int_t iStartDigi, Bool_t bSts, Bool_t bMuch, Bool_t bTof ) { Int_t nrDigis=array->GetEntriesFast(); Int_t iFirstDigiInWin = iStartDigi; for (Int_t i = iStartDigi; i < nrDigis; ++i) { CbmDigi* Digi = static_cast(array->At(i)); if( kTRUE == bTof ) if( 92 < Digi->GetCharge() && Digi->GetCharge() < 96 ) continue; Double_t diffTime = T0Time - Digi->GetTime(); if (diffTime > offsetRange) { ++ iFirstDigiInWin; // Update Index of first digi in Win to next digi continue; // not yet in interesting range } // if (diffTime > offsetRange) if (diffTime < -offsetRange) break; // already past interesting range histo->Fill(diffTime); histoCharge->Fill( diffTime, Digi->GetCharge() ); histoEvo->Fill(fNrTs, diffTime); histoEvoLong->Fill(fNrTs, diffTime); /// STS DPB mapping: ladder 1 is in DPB 1 if (bSts && histoAFCK) { UInt_t uDPB = ( 0 < (Digi->GetAddress() & 0x00000400 ) ); histoAFCK->Fill(uDPB, diffTime); if( uDPB < kuMaxNbStsDpbs ) fT0StsDpbDiffEvo[ uDPB ]->Fill(fNrTs, diffTime); } // if (bSts && histoAFCK) /// MUCH DPB mapping if (bMuch && histoAFCK) { // Int_t afck = static_cast(Digi)->GetRocId(); UInt_t afck = static_cast(Digi)->GetNxId(); histoAFCK->Fill(afck, diffTime); if( afck < kuMaxNbMuchAsics ) fT0MuchAsicDiffEvo[ afck ]->Fill(fNrTs, diffTime); } // if (bMuch && histoAFCK) } return iFirstDigiInWin; } void CbmCheckTiming::CheckTimeOrder() { if (fT0Digis) { Int_t nrT0Digis = fT0Digis->GetEntriesFast(); fNrOfT0Digis += nrT0Digis; fNrOfT0Errors += CheckIfSorted(fT0Digis, fT0T0Diff, fPrevTimeT0, "T0"); } if (fStsDigis) { Int_t nrStsDigis = fStsDigis->GetEntriesFast(); fNrOfStsDigis += nrStsDigis; fNrOfStsErrors += CheckIfSorted(fStsDigis, fStsStsDiff, fPrevTimeSts, "Sts"); for (Int_t i = 0; i < nrStsDigis; ++i) { CbmDigi* Digi = static_cast(fStsDigis->At(i)); UInt_t uDPB = ( 0 < (Digi->GetAddress() & 0x00000400 ) ); if( uDPB < kuMaxNbStsDpbs ) fStsDpbCntsEvo[ uDPB ]->Fill( fNrTs ); } } if (fMuchDigis) { Int_t nrMuchDigis = fMuchDigis->GetEntriesFast(); fNrOfMuchDigis += nrMuchDigis; fNrOfMuchErrors += CheckIfSorted(fMuchDigis, fMuchMuchDiff, fPrevTimeMuch, "Much"); } if (fTofDigis) { Int_t nrTofDigis = fTofDigis->GetEntriesFast(); fNrOfTofDigis += nrTofDigis; fNrOfTofErrors += CheckIfSorted(fTofDigis, fTofTofDiff, fPrevTimeTof, "Tof"); } if (fRichDigis) { Int_t nrRichDigis = fRichDigis->GetEntriesFast(); fNrOfRichDigis += nrRichDigis; fNrOfRichErrors += CheckIfSorted(fRichDigis, fRichRichDiff, fPrevTimeRich, "Rich"); } } Int_t CbmCheckTiming::CheckIfSorted(TClonesArray* array, TH1* histo, Double_t& prevTime, TString detector) { Int_t nrOfErrors=0; Int_t nrDigis=array->GetEntriesFast(); for (Int_t i = 0; i < nrDigis; ++i) { CbmDigi* digi = static_cast(array->At(i)); Double_t diffTime = digi->GetTime() - prevTime; histo->Fill(diffTime); if (diffTime < 0.) { LOG(info) << fixed << setprecision(15) << diffTime << "ns"; LOG(info) << "Previous " << detector << " digi (" << fixed << setprecision(15) << prevTime * 1.e-9 << ") has a larger time than the current one (" << digi->GetTime() * 1.e-9 << ") for digi " << i << " of ts " << fNrTs; nrOfErrors++; } prevTime = digi->GetTime(); } return nrOfErrors; } // ---- Finish -------------------------------------------------------- void CbmCheckTiming::Finish() { if (fCheckTimeOrdering) { LOG(info) << "Total number of T0 out of order digis: " << fNrOfT0Errors; LOG(info) << "Total number of T0 digis: " << fNrOfT0Digis; LOG(info) << "Total number of Sts out of order digis: " << fNrOfStsErrors; LOG(info) << "Total number of Sts digis: " << fNrOfStsDigis; LOG(info) << "Total number of Much out of order digis: " << fNrOfMuchErrors; LOG(info) << "Total number of Much digis: " << fNrOfMuchDigis; LOG(info) << "Total number of Tof out of order digis: " << fNrOfTofErrors; LOG(info) << "Total number of Tof digis: " << fNrOfTofDigis; LOG(info) << "Total number of Rich out of order digis: " << fNrOfRichErrors; LOG(info) << "Total number of Rich digis: " << fNrOfRichDigis; } WriteHistos(); } void CbmCheckTiming::WriteHistos() { TFile* old = gFile; TFile* outfile = TFile::Open(fOutFileName,"RECREATE"); fT0StsDiff->Write(); fT0MuchDiff->Write(); fT0TofDiff->Write(); fT0RichDiff->Write(); fT0StsDiffCharge->Write(); fT0MuchDiffCharge->Write(); fT0TofDiffCharge->Write(); fT0RichDiffCharge->Write(); fT0StsDiffEvo->Write(); fT0MuchDiffEvo->Write(); fT0TofDiffEvo->Write(); fT0RichDiffEvo->Write(); fT0StsDiffEvoLong->Write(); fT0MuchDiffEvoLong->Write(); fT0TofDiffEvoLong->Write(); fT0RichDiffEvoLong->Write(); fT0T0Diff->Write(); fStsStsDiff->Write(); fMuchMuchDiff->Write(); fTofTofDiff->Write(); fRichRichDiff->Write(); fT0Address->Write(); fT0Channel->Write(); fT0StsDpbDiff->Write(); for( UInt_t uStsDpb = 0; uStsDpb < kuMaxNbStsDpbs; ++uStsDpb ) { fT0StsDpbDiffEvo[uStsDpb]->Write(); fStsDpbCntsEvo[uStsDpb]->Write(); } fT0MuchRocDiff->Write(); for( UInt_t uMuchAsic = 0; uMuchAsic < kuMaxNbMuchAsics; ++uMuchAsic ) fT0MuchAsicDiffEvo[uMuchAsic]->Write(); outfile->Close(); delete outfile; gFile = old; } ClassImp(CbmCheckTiming)