/**@file CbmTbReceiver.cxx **@date 29.06.2009 **@author V. Friese **/ #include "CbmTbReceiver.h" #include "CbmTbEvent.h" #include "CbmMuchDigi.h" #include "CbmStsDigi.h" #include "CbmRichDigi.h" #include #include #include "TClonesArray.h" #include "FairRootManager.h" // ----- Default Constructor ---------------------------------------------- CbmTbReceiver::CbmTbReceiver() : FairTask("CBM Testbeam Receiver") { } // --------------------------------------------------------------------------- // ----- Standard Constructor --------------------------------------------- CbmTbReceiver::CbmTbReceiver(const char* inFile, Double_t timeWindow, Int_t iVerbose, const char* name) : FairTask(name, iVerbose), fInputFileName(inFile), fTimeWindow(timeWindow), fBeamRoc(-1), fBeamAuxChn(-1), fPersistence(kTRUE), fLastMsgTime(0.), fLastEventTime(0.), fCurrentEpochTime(0.), fNofMessages(0), fNofEvents(0), fEvents(NULL), fStsDigis(NULL), fMuchDigis(NULL), fCurrentMessage(NULL), fCurrentEvent(NULL) { } // --------------------------------------------------------------------------- // ----- Destructor ------------------------------------------------------ CbmTbReceiver::~CbmTbReceiver() { } // --------------------------------------------------------------------------- // ----- Task execution --------------------------------------------------- void CbmTbReceiver::Exec(Option_t* opt) { if ( fVerbose) cout << endl << "-I- " << GetName() << "::Exec event " << fNofEvents << endl; // Clear output arrays fEvents->Clear(); fStsDigis->Clear(); fMuchDigis->Clear(); fRichDigis->Clear(); // No action if no message available if ( ! fCurrentMessage ) { cout << "-" << GetName() << ": No more mssages in input file." << endl; return; } // Create new CBM event fCurrentEvent = new((*fEvents)[0]) CbmTbEvent(); fNofEvents++; // --- Loop over messages until event end while (fCurrentMessage) { // --- Treat epoch markers if ( fCurrentMessage->isEpochMsg() ) { fCurrentEpoch = fCurrentMessage->getEpochNumber(); fCurrentEpochTime = Double_t(fCurrentMessage->getMsgFullTime(fCurrentEpoch)) * 1e-9; fNofEpochs++; if ( fVerbose ) cout << "-I- " << GetName() << ": Epoch message " << fNofEpochs << ", epoch " << Int_t(fCurrentEpoch) << ", time " << setprecision(9) << fixed << fCurrentEpochTime << " s" << endl; } // --- Epoch marker ? // --- Treat beam counters (aux messages) else if ( fCurrentMessage->isAuxMsg() ) { Int_t iRoc = Int_t(fCurrentMessage->getRocNumber()); Double_t auxTime = Double_t(fCurrentMessage->getMsgFullTime(fCurrentEpoch)) * 1e-9; Double_t tDiff = 1e9 * (auxTime - fCurrentEvent->GetTime()); Int_t auxChn = Int_t(fCurrentMessage->getAuxChNum()); if ( fVerbose >= 2 ) cout << "-I- " << GetName() << ": Aux message, ROC " << iRoc << ", channel " << auxChn << ", time " << setprecision(9) << fixed << auxTime << " s" << endl; // Check message time CheckMessage(auxTime); // Discard if not set as beam signal if ( iRoc == fBeamRoc && auxChn == fBeamAuxChn ) { // --- Check whether aux belongs to current event if ( fCurrentEvent->IsEmpty() || tDiff < fTimeWindow ) { if ( fVerbose >= 2) { if ( fCurrentEvent->IsEmpty() ) cout << "-I- " << GetName() << ": Current event is empty, matching aux." << endl; else cout << "-I- " << GetName() << setprecision(9) << fixed << ": Match to event, aux time " << auxTime << " s, event " << fCurrentEvent->GetTime() << " s, diff " << setprecision(0) << 1e9 * ( auxTime - fCurrentEvent->GetTime() ) << " ns, window " << fTimeWindow << " ns" << endl; } fCurrentEvent->AddBeam(auxTime, fCurrentEpochTime); } // Aux belongs to event // --- If aux does not belong to current event: End execution else { if ( fVerbose >=2 ) { cout << "-I- " << GetName() << ": Time difference to event (" << setprecision(0) << tDiff << " ns) exceeds time window (" << fTimeWindow << " ns); closing event." << endl; fCurrentEvent->Print(); } if (! fVerbose) cout << "+ " << GetName() << ": Event " << fNofEvents-1 << ", time " << setprecision(9) << fixed << fCurrentEvent->GetTime() << setprecision(0) << " s, Duration " << fCurrentEvent->GetDuration() *1e9 << " ns, Messages " << fCurrentEvent->GetNofMessages() << endl; return; } // --- End of event } // --- Beam signal message? } // Aux message? // --- Treat hit messages else if ( fCurrentMessage->isHitMsg() ) { // Absolute hit time and difference to event time Double_t hitTime = Double_t(fCurrentMessage->getMsgFullTime(fCurrentEpoch)) * 1e-9; Double_t tDiff = 1e9 * (hitTime - fCurrentEvent->GetTime()); if ( fVerbose >= 2 ) cout << "-I- " << GetName() << ": Hit message, ROC " << Int_t(fCurrentMessage->getRocNumber()) << ", NXYTER " << Int_t(fCurrentMessage->getNxNumber()) << ", channel " << Int_t(fCurrentMessage->getNxChNum()) << ", time " << setprecision(9) << fixed << hitTime << " s" << endl; // --- Check whether hit belongs to current event if ( fCurrentEvent->IsEmpty() || tDiff < fTimeWindow ) { if ( fVerbose >= 2) { if ( fCurrentEvent->IsEmpty() ) cout << "-I- " << GetName() << ": Current event is empty, matching hit." << endl; else cout << "-I- " << GetName() << setprecision(9) << fixed << ": Match to event, hit " << hitTime << " s, event " << fCurrentEvent->GetTime() << " s, diff " << setprecision(0) << 1e9 * ( hitTime - fCurrentEvent->GetTime() ) << " ns, window " << fTimeWindow << " ns" << endl; } Int_t iRoc = Int_t(fCurrentMessage->getRocNumber()); Int_t iNx = Int_t(fCurrentMessage->getNxNumber()); // Check whether ROC is registered if ( fRocDetMap.find(iRoc) == fRocDetMap.end() ) { cout << "-E- CbmTbReceiver::Exec:: ROC number " << iRoc << " not registered! Aborting run..." << endl; Fatal("Exec", "Unknown ROC"); } // --- Treat STS messages if ( fRocDetMap[iRoc] == kSTS ) { Int_t iStation, iSector, iSide, iChannel; if ( fDaqMap ) fDaqMap->Map(iRoc, iNx, fCurrentMessage->getNxChNum(), iStation, iSector, iSide, iChannel); else { iStation = iRoc; iSector = iNx; iSide = 0; iChannel = fCurrentMessage->getNxChNum(); } AddStsDigi(iStation, iSide, Double_t(iChannel), Double_t(fCurrentMessage->getNxAdcValue()), hitTime); } // STS message? // Treat MUCH messages else if ( fRocDetMap[iRoc] == kMUCH ) { Int_t detId = 10*iRoc + iNx; Int_t iChannel = Int_t(fCurrentMessage->getNxChNum()); Double_t adc = Double_t(fCurrentMessage->getNxAdcValue()); AddMuchDigi(detId, iChannel, adc, hitTime); } // --- Treat RICH messages else if ( fRocDetMap[iRoc] == kRICH ) { Int_t iStation = iRoc; Int_t channel = Int_t(fCurrentMessage->getNxChNum()); Int_t adc = Int_t(fCurrentMessage->getNxAdcValue()); AddRichDigi(channel, adc, hitTime); } // --- Unknown detector type else { cout << "-E- CbmTbReceiver::Exec: Unknwon detector type " << fRocDetMap[iRoc] << " for ROC " << iRoc << ", aborting run." << endl; Fatal("Exec", "Unknwon detector type"); } } // --- Hit belongs to current event ? // --- If hit does not belong to current event: End execution else { if ( fVerbose >=2 ) { cout << "-I- " << GetName() << ": Time difference to event (" << setprecision(0) << tDiff << " ns) exceeds time window (" << fTimeWindow << " ns); closing event." << endl; fCurrentEvent->Print(); } if (! fVerbose) cout << "+ " << GetName() << ": Event " << fNofEvents-1 << ", time " << setprecision(9) << fixed << fCurrentEvent->GetTime() << setprecision(0) << " s, Duration " << fCurrentEvent->GetDuration() *1e9 << " ns, Messages " << fCurrentEvent->GetNofMessages() << endl; return; } // --- End of event } // --- Hit message ? // Next ROC message if ( fRocIter->next() ) { fCurrentMessage = &fRocIter->msg(); fNofMessages++; } else fCurrentMessage = NULL; } // --- ROC message loop } // --------------------------------------------------------------------------- // ----- Add a ROC ------------------------------------------------------- void CbmTbReceiver::AddRoc(Int_t rocId, DetectorId detType) { if ( fRocDetMap.find(rocId) != fRocDetMap.end() ) cout << "-W- CbmTbReceiver::AddRoc:: Replacing ROC " << rocId << ", Det " << fRocDetMap[rocId] << " !" << endl; fRocDetMap[rocId] = detType; } // --------------------------------------------------------------------------- // ----- Set ROC and AUX channel for beam signal ------------------------- void CbmTbReceiver::SetBeam(Int_t rocId, Int_t auxChn) { fBeamRoc = rocId; fBeamAuxChn = auxChn; } // --------------------------------------------------------------------------- // ----- Initialisation ---------------------------------------------------- InitStatus CbmTbReceiver::Init() { cout << endl << endl; cout << "===== " << GetName() << ": Intialising ..." << endl; // Check whether run settings are set if ( ! fDaqMap ) { cout << "-E- " << fName << "::Init: No run settings made!" << endl; return kFATAL; } // Check and open input file cout << "===== Opening file " << fInputFileName << endl; fRocIter = new roc::Iterator(fInputFileName.Data()); if ( ! fRocIter->next() ) { cout << "-E- " << GetName() << "::Init: input file does not exist " << "or is empty!" << endl; return kFATAL; } fCurrentMessage = &fRocIter->msg(); fNofMessages++; // Register output branches FairRootManager* ioman = FairRootManager::Instance(); fEvents = new TClonesArray("CbmTbEvent", 1); ioman->Register("TBEvent", "Testbeam event", fEvents, fPersistence); fStsDigis = new TClonesArray("CbmStsDigi", 10); ioman->Register("STSDigi", "STS raw data", fStsDigis, fPersistence); fMuchDigis = new TClonesArray("CbmMuchDigi", 10); ioman->Register("MUCHDigi", "MUCH raw data", fMuchDigis, fPersistence); fRichDigis = new TClonesArray("CbmRichDigi", 10); ioman->Register("RICHDigi", "RICH raw data", fRichDigis, fPersistence); cout << "===== Initialisation done. " << endl; return kSUCCESS; } // --------------------------------------------------------------------------- // ----- Re-Initialisation ------------------------------------------------- InitStatus CbmTbReceiver::ReInit() { return kSUCCESS; } // --------------------------------------------------------------------------- // ----- Finish run ------------------------------------------------------- void CbmTbReceiver::Finish() { cout << endl << endl; cout << "==========================================================" << endl; cout << "-I- " << GetName() << ": Run summary" << endl; cout << "-I" << endl; cout << "-I- Number of ROC messages processed : " << fNofMessages << endl; cout << "-I- Number of epochs : " << fNofEpochs << endl; cout << "-I- Number of TbEvents created : " << fNofEvents << endl; cout << "==========================================================" << endl; } // --------------------------------------------------------------------------- // ----- Add a STS digi --------------------------------------------------- void CbmTbReceiver::AddStsDigi(Int_t iStation, Int_t iSide, Double_t channel, Double_t adc, Double_t time) { if ( iSide < 0 || iSide > 1 ) { cout << "-E- CbmTbReceiver::AddStsDigi:: Illegal side number " << iSide << ", aborting run." << endl; Fatal("AddStsDigi", "Illegal side"); } Int_t iDigi = fStsDigis->GetEntriesFast(); if ( fVerbose >= 3 ) cout << "-I- " << GetName() << ": Creating STS digi " << iDigi << ", Station " << iStation << ", Side " << iSide << setprecision(0) << ", channel " << channel << ", ADC " << adc << setprecision(9) << fixed << ", time " << time << " s" << endl; CbmStsDigi* digi = new ((*fStsDigis)[iDigi]) CbmStsDigi(iStation, 1, iSide, channel, adc, time ); // Update CbmTbEvent fCurrentEvent->AddStsData(digi, fCurrentEpochTime); if (fVerbose) { cout << "-I- " << GetName() << ": Updating event.." << endl; fCurrentEvent->Print(); } } // --------------------------------------------------------------------------- // ----- Add a MUCH digi --------------------------------------------------- void CbmTbReceiver::AddMuchDigi(Int_t iStation, Int_t iChannel, Double_t adc, Double_t time) { Int_t iDigi = fMuchDigis->GetEntriesFast(); if ( fVerbose >= 3 ) cout << "-I- " << GetName() << ": Creating MUCH digi " << iDigi << ", Station " << iStation << setprecision(0) << ", channel " << iChannel << ", ADC " << adc << setprecision(9) << fixed << ", time " << time << " s" << endl; CbmMuchDigi* digi = new ((*fMuchDigis)[iDigi]) CbmMuchDigi(iStation, iChannel, time, 0., adc ); // Update CbmTbEvent fCurrentEvent->AddMuchData(digi, fCurrentEpochTime); if (fVerbose) { cout << "-I- " << GetName() << ": Updating event.." << endl; fCurrentEvent->Print(); } } // --------------------------------------------------------------------------- // ----- Add a RICH digi --------------------------------------------------- void CbmTbReceiver::AddRichDigi(Int_t channel, Int_t adc, Double_t time) { Int_t iDigi = fRichDigis->GetEntriesFast(); if ( fVerbose >= 3 ) cout << "-I- " << GetName() << ": Creating RICH digi " << iDigi << setprecision(0) << ", channel " << channel << ", ADC " << adc << setprecision(9) << fixed << ", time " << time << " s" << endl; CbmRichDigi* digi = new ((*fRichDigis)[iDigi]) CbmRichDigi(channel, adc, time); // Update CbmTbEvent fCurrentEvent->AddRichData(digi, fCurrentEpochTime); if (fVerbose) { cout << "-I- " << GetName() << ": Updating event.." << endl; fCurrentEvent->Print(); } } // --------------------------------------------------------------------------- // ----- Check message time ordering -------------------------------------- void CbmTbReceiver::CheckMessage(Double_t time) { if ( time < fLastMsgTime ) { cout << "-E- " << GetName() << ": Message time " << setprecision(9) << fixed << time << " s before last message time " << fLastMsgTime << " s!! Aborting run..." << endl; Fatal("CheckMessage", "Time disordering"); } fLastMsgTime = time; } // --------------------------------------------------------------------------- ClassImp(CbmTbReceiver)