/** * @file * @author Christian Simon * @since 2017-06-01 */ #include "CbmTofDigitizeDev.h" #include "CbmTofDigiTbPar.h" #include "CbmTofCounter.h" #include "CbmTofMemory.h" #include "CbmTofPoint.h" #include "CbmTofGeoHandler.h" #include "CbmMCBuffer.h" #include "CbmTofWall.h" #include "CbmDaqPointBuffer.h" #include "CbmTofDigiExp.h" #include "CbmMatch.h" #include "CbmDaq.h" #include "FairRun.h" #include "FairRootManager.h" #include "FairRuntimeDb.h" #include "FairLogger.h" #include "FairEventHeader.h" // --------------------------------------------------------------------------- CbmTofDigitizeDev::CbmTofDigitizeDev() : CbmDigitize("CbmTofDigitizeDev"), fDigiTbParSet(NULL), fGeoHandler(new CbmTofGeoHandler()), fbMemorizeCharges(kFALSE), fbGenerateDarkRate(kFALSE), fbCalibrateDigis(kFALSE), fiNMemoryThreads(1), fbRemoveHitsFromMemory(kFALSE), fdHitRemovalCriterion(0.001), fbSendPointsToDAQ(kFALSE), fdPreviousPointTime(0.), fbClearMemorySB(kTRUE), fdSpillBreakLength(1.), fdEventTimeOffset(0.), fTofDigis(NULL), fTofPointsTB(NULL), fPointBuffer(NULL), fPointIndices(), fbAlternativeBranchNames(kFALSE), fiFileIndex(0) { } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- CbmTofDigitizeDev::~CbmTofDigitizeDev() { if(fGeoHandler) { delete fGeoHandler; } } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofDigitizeDev::Exec(Option_t */*option*/) { // Make sure that 'CbmDaq' uses the correct file ID in its MC event list. // The method 'FairFileSource::FillEventHeader' always sets it to '0'. FairRun::Instance()->GetEventHeader()->SetInputFileId(fiFileIndex); if(fbGenerateDarkRate) { // Generate dark rate points with timestamps up to the current event start time // and fill them into 'CbmMCPointBuffer'. for(auto const & itCounter : CbmTofWall::Instance()->GetDarkRateCounterMap()) { (itCounter.second)->GenerateDarkRate(FairRootManager::Instance()->GetEventTime()); } } const CbmTofPoint* tTofPoint = dynamic_cast(CbmMCBuffer::Instance()->GetNextPoint(kTof)); while(tTofPoint) { // Check for spill transitions based on time intervals between source rate points only if(-1 != tTofPoint->GetEventID()) { // Account for multiple spills simulated in the same run. if(tTofPoint->GetTime() - fdPreviousPointTime > fdSpillBreakLength/2.*1e9) { if(fbClearMemorySB && fdPreviousPointTime) { CbmTofMemory::Instance()->ClearMemory(); } } } Int_t iTofPointAddress = tTofPoint->GetDetectorID(); if(0 != fGeoHandler->GetGap(iTofPointAddress) || 0 != fGeoHandler->GetCell(iTofPointAddress)) { LOG(FATAL)<<"Multiple ToF points per MC track and MRPC found. Please rerun the MC simulation with CbmTof::fbOnePointPerTrack enabled."<GetCounter(iTofPointAddress); if(tCounter) { if(fbSendPointsToDAQ) { fPointBuffer->InsertData(kTof, new CbmTofPoint(*tTofPoint)); } tCounter->ProcessPoint(tTofPoint); } if(-1 != tTofPoint->GetEventID()) { fdPreviousPointTime = tTofPoint->GetTime(); } tTofPoint = dynamic_cast(CbmMCBuffer::Instance()->GetNextPoint(kTof)); } for(auto const & itCounter : CbmTofWall::Instance()->GetCounterMap()) { (itCounter.second)->ReadOutChannelBuffers(FairRootManager::Instance()->GetEventTime()); } } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofDigitizeDev::FinishEvent() { } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofDigitizeDev::ResetArrays() { fTofDigis->Delete(); if(fbSendPointsToDAQ) { fTofPointsTB->Delete(); fPointIndices.clear(); } } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofDigitizeDev::WriteDigi(CbmDigi* digi, CbmMatch* match) { if(fbSendPointsToDAQ) { Int_t iTimesliceIndex = FairRootManager::Instance()->GetOutTree()->GetEntries(); Int_t iNMCLinks = digi->GetMatch()->GetNofLinks(); for(Int_t iLink = 0; iLink < iNMCLinks; iLink++) { CbmLink& tLink = digi->GetMatch()->GetLink(iLink); Int_t iTempPointIndex = tLink.GetIndex(); auto const & itIndex = fPointIndices.find(iTempPointIndex); // If a MC point contributing to the digi is not available in the // current timeslice (the point was attributed to the previous TS // while the digi is attributed to the current one), the corresponding // 'CbmLink' information cannot be updated concerning the position of // the MC point in the TS. In the MC event building algorithm, however, // every digi needs to be assigned to a MC event. If 'CbmLink::fIndex' // is found to equal -1, then 'CbmLink::fEntry' still contains the // original MC tree entry number, i.e. the event number. In all other // cases, the MC point is available in the same TS and its event // number must be retrieved from 'FairMCPoint::fEventID'. if(itIndex != fPointIndices.end()) { tLink.SetFile(fiFileIndex); tLink.SetIndex(itIndex->second); tLink.SetEntry(iTimesliceIndex); } else { tLink.SetFile(fiFileIndex); tLink.SetIndex(-1); // The point object has already been saved to disk and cannot be // notified anymore about (some of) its digis being written to a // different timeslice. } } } new((*fTofDigis)[fTofDigis->GetEntriesFast()]) CbmTofDigiExp(*dynamic_cast(digi)); } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofDigitizeDev::FillCustomData(Double_t fillTime, Bool_t limit) { if(fbSendPointsToDAQ) { CbmDaq* tDaqTask = dynamic_cast(FairRun::Instance()->GetTask("Daq")); FairMCPoint* point = ( limit ? fPointBuffer->GetNextData(kTof, fillTime) : fPointBuffer->GetNextData(kTof) ); while(point) { CbmTofPoint* tOldPoint = dynamic_cast(point); Int_t iPointIndex = fTofPointsTB->GetEntriesFast(); fPointIndices.emplace(tOldPoint->GetUniqueID(), iPointIndex); tOldPoint->SetUniqueID(fiFileIndex); // In 'CbmDaq', only the sampled event start times of those MC events are // are stored in the "MCEventList." branch that are referred to by // MC point backlinks of digi objects. Thus, the start time of an event // wherein no MC point led to the creation of a digi would not be available // during reconstruction, although the position of such entirely "inefficient" // events on the common experiment time axis might be of interest for detector // response studies. For this reason, events containing any MC points // are registered manually with the event list administered by 'CbmDaq'. Int_t iEventID = tOldPoint->GetEventID(); if(-1 != iEventID) { tDaqTask->RegisterEvent(fiFileIndex, iEventID); } new((*fTofPointsTB)[iPointIndex]) CbmTofPoint(*tOldPoint); delete tOldPoint; point = ( limit ? fPointBuffer->GetNextData(kTof, fillTime) : fPointBuffer->GetNextData(kTof) ); } } } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- InitStatus CbmTofDigitizeDev::Init() { if(!(FairRun::Instance()->GetTask("MCTimeSim") && FairRun::Instance()->GetTask("Daq"))) { LOG(ERROR)<<"FairTask implementations CbmMCTimeSim and CbmDaqNew not in task list."<Init(kFALSE); if(k12b > iGeoVersion) { LOG(ERROR)<<"ToF geometry version must at least be 'v12b'."<Initialize(fDigiTbParSet))) { return kFATAL; } // NOTE: The following counter parameters are set AFTER 'CbmTofCounter::Initialize' // has been called. for(auto const & itCounter : CbmTofWall::Instance()->GetCounterMap()) { (itCounter.second)->SetSendChargesToMemory(fbMemorizeCharges); (itCounter.second)->SetCalibrateDigis(fbCalibrateDigis); (itCounter.second)->SetEventTimeOffset(fdEventTimeOffset); (itCounter.second)->SetFileIndex(fiFileIndex); } if(fbMemorizeCharges) { CbmTofMemory* tTofMemory = CbmTofMemory::Instance(); tTofMemory->SetNThreads(fiNMemoryThreads); tTofMemory->SetRemoveHitsFromMemory(fbRemoveHitsFromMemory); tTofMemory->SetHitRemovalCriterion(fdHitRemovalCriterion); tTofMemory->Initialize(CbmTofWall::Instance()->GetMemoryCounterMap()); } TString tPointBranchName; TString tDigiBranchName; if(fbAlternativeBranchNames) { tPointBranchName = "ATofPointTB"; tDigiBranchName = "ATofDigiExp"; } else { tPointBranchName = "TofPointTB"; tDigiBranchName = "TofDigiExp"; } fTofDigis = new TClonesArray("CbmTofDigiExp", 1000); FairRootManager::Instance()->Register(tDigiBranchName, "TOF digis", fTofDigis, IsOutputBranchPersistent(tDigiBranchName)); if(fbSendPointsToDAQ) { fTofPointsTB = new TClonesArray("CbmTofPoint", 1000); FairRootManager::Instance()->Register(tPointBranchName, "TOF points TB", fTofPointsTB, IsOutputBranchPersistent(tPointBranchName)); fPointBuffer = CbmDaqPointBuffer::Instance(); } return kSUCCESS; } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofDigitizeDev::SetParContainers() { FairRun* tRun = FairRun::Instance(); if(!tRun) { LOG(FATAL)<GetRuntimeDb(); if(!tDataBase) { LOG(FATAL)<(tDataBase->getContainer("CbmTofDigiTbPar")); } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofDigitizeDev::Finish() { // Make sure that 'CbmDaq' uses the correct file ID in its MC event list. // The method 'FairFileSource::FillEventHeader' always sets it to '0'. FairRun::Instance()->GetEventHeader()->SetInputFileId(fiFileIndex); if(fbGenerateDarkRate) { // Generate dark rate points with timestamps up to the hypothetical start time // of an event occurring after the last event provided by the framework and // fill them into 'CbmMCPointBuffer'. for(auto const & itCounter : CbmTofWall::Instance()->GetDarkRateCounterMap()) { (itCounter.second)->GenerateDarkRate(FairRootManager::Instance()->GetEventTime()); } } // readout of all MC points remaining in the buffer const CbmTofPoint* tTofPoint = dynamic_cast(CbmMCBuffer::Instance()->GetNextPoint(kTof)); while(tTofPoint) { // Check for spill transitions based on time intervals between source rate points only if(-1 != tTofPoint->GetEventID()) { // Account for multiple spills simulated in the same run. if(tTofPoint->GetTime() - fdPreviousPointTime > fdSpillBreakLength/2.*1e9) { if(fbClearMemorySB && fdPreviousPointTime) { CbmTofMemory::Instance()->ClearMemory(); } } } Int_t iTofPointAddress = tTofPoint->GetDetectorID(); if(0 != fGeoHandler->GetGap(iTofPointAddress) || 0 != fGeoHandler->GetCell(iTofPointAddress)) { LOG(FATAL)<<"Multiple ToF points per MC track and MRPC found. Please rerun the MC simulation with CbmTof::fbOnePointPerTrack enabled."<GetCounter(iTofPointAddress); if(tCounter) { if(fbSendPointsToDAQ) { fPointBuffer->InsertData(kTof, new CbmTofPoint(*tTofPoint)); } tCounter->ProcessPoint(tTofPoint); } if(-1 != tTofPoint->GetEventID()) { fdPreviousPointTime = tTofPoint->GetTime(); } tTofPoint = dynamic_cast(CbmMCBuffer::Instance()->GetNextPoint(kTof)); } for(auto const & itCounter : CbmTofWall::Instance()->GetCounterMap()) { // trigger complete readout of all channel buffers (itCounter.second)->ReadOutChannelBuffers(-1.); } if(fbMemorizeCharges) { CbmTofMemory* tTofMemory = CbmTofMemory::Instance(); tTofMemory->Finish(); } } // --------------------------------------------------------------------------- ClassImp(CbmTofDigitizeDev)