/** * @file * @author Christian Simon * @since 2018-05-31 */ #include "CbmTofBuildDigiEvents.h" #include "CbmTimeSlice.h" #include "CbmTofDigiExp.h" #include "CbmMatch.h" #include "CbmMCEventList.h" //#include "CbmTofDef.h" TODO #include "FairLogger.h" #include "FairRootManager.h" #include "FairFileSource.h" #include "TClonesArray.h" #include "TMath.h" #include // --------------------------------------------------------------------------- CbmTofBuildDigiEvents::CbmTofBuildDigiEvents() : FairTask("TofBuildDigiEvents"), fFileSource(NULL), fTimeSliceHeader(NULL), fTofTimeSliceDigis(NULL), fInputMCEventList(NULL), fOutputMCEventList(NULL), fTofEventDigis(NULL), fdEventWindow(0.), fNominalTriggerCounterMultiplicity(), fiTriggerMultiplicity(0), fbPreserveMCBacklinks(kFALSE), fbMCEventBuilding(kFALSE), fdEventStartTime(DBL_MIN), fCounterMultiplicity(), fdIdealEventWindow(1000.), fProcessedIdealEvents(), fIdealEventStartTimes(), fIdealEventDigis(), fiNEvents(0), fdDigiToTOffset(0.), fInactiveCounterSides(), fbRealData(kFALSE), fCounterORGroups(), fCounterORPartners(), fStartCounters() { } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- CbmTofBuildDigiEvents::~CbmTofBuildDigiEvents() { } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofBuildDigiEvents::Exec(Option_t*) { if(fbMCEventBuilding) { ProcessIdealEvents(fTimeSliceHeader->GetStartTime()); for(Int_t iDigi = 0; iDigi < fTofTimeSliceDigis->GetEntriesFast(); iDigi++) { CbmTofDigiExp* tDigi = dynamic_cast(fTofTimeSliceDigis->At(iDigi)); Int_t iDigiAddress = tDigi->GetAddress(); Double_t dDigiTime = tDigi->GetTime(); Double_t dDigiToT = tDigi->GetTot(); Int_t iNMCLinks = tDigi->GetMatch()->GetNofLinks(); for(Int_t iLink = 0; iLink < iNMCLinks; iLink++) { const CbmLink& tLink = tDigi->GetMatch()->GetLink(iLink); // Only consider digis that contain at least one contribution from a // primary source signal. If the digi contains primary signal contributions // from more than one MC event, assign the digi to all MC events found. // TODO: Replace '0' by 'tof::signal_SourcePrimary' upon inclusion of // 'tof/TofTools/CbmTofDef.h' into trunk! if(0 == tLink.GetUniqueID()) { std::pair EventID(tLink.GetFile(), tLink.GetEntry()); // The MC event is already known. if(fIdealEventStartTimes.find(EventID) != fIdealEventStartTimes.end()) { auto & DigiVector = fIdealEventDigis.at(EventID); if(fbPreserveMCBacklinks) { // deep copy construction including 'CbmDigi::fMatch' DigiVector.push_back(new CbmTofDigiExp(*tDigi)); } else { // shallow construction excluding 'CbmDigi::fMatch' DigiVector.push_back(new CbmTofDigiExp(iDigiAddress, dDigiTime, dDigiToT)); } } // The MC event is not known yet. else { // Make sure that a late digi from an event that has already been // processed and written to disk (i.e. the time difference to the // earliest digi in the same event is larger than 'fdIdealEventWindow') // does not trigger separate event processing for itself only // (and possibly a few additional latecomers). if(fProcessedIdealEvents.find(EventID) == fProcessedIdealEvents.end()) { fIdealEventStartTimes.emplace(EventID, dDigiTime); fIdealEventDigis.emplace(EventID, std::vector()); auto & DigiVector = fIdealEventDigis.at(EventID); if(fbPreserveMCBacklinks) { // deep copy construction including 'CbmDigi::fMatch' DigiVector.push_back(new CbmTofDigiExp(*tDigi)); } else { // shallow construction excluding 'CbmDigi::fMatch' DigiVector.push_back(new CbmTofDigiExp(iDigiAddress, dDigiTime, dDigiToT)); } } } } } } } else { for(Int_t iDigi = 0; iDigi < fTofTimeSliceDigis->GetEntriesFast(); iDigi++) { CbmTofDigiExp* tDigi = dynamic_cast(fTofTimeSliceDigis->At(iDigi)); Int_t iDigiModuleType = tDigi->GetType(); Int_t iDigiModuleIndex = tDigi->GetSm(); Int_t iDigiCounterIndex = tDigi->GetRpc(); Int_t iDigiCounterSide = tDigi->GetSide(); Int_t iDigiAddress = tDigi->GetAddress(); Double_t dDigiTime = tDigi->GetTime(); Double_t dDigiToT = tDigi->GetTot(); auto CounterTuple = std::make_tuple(iDigiModuleType, iDigiModuleIndex, iDigiCounterIndex); auto CounterSideTuple = std::make_tuple(iDigiModuleType, iDigiModuleIndex, iDigiCounterIndex, iDigiCounterSide); if(dDigiTime - fdEventStartTime > fdEventWindow) { std::map, UChar_t> ActualTriggerCounterMultiplicity; std::set_intersection(fCounterMultiplicity.begin(), fCounterMultiplicity.end(), fNominalTriggerCounterMultiplicity.begin(), fNominalTriggerCounterMultiplicity.end(), std::inserter(ActualTriggerCounterMultiplicity, ActualTriggerCounterMultiplicity.begin())); if(ActualTriggerCounterMultiplicity.size() >= fiTriggerMultiplicity) { if(fbPreserveMCBacklinks) { FillMCEventList(); } FairRootManager::Instance()->Fill(); fiNEvents++; fOutputMCEventList->Clear(""); fTofEventDigis->Delete(); } else { fTofEventDigis->Delete(); } fCounterMultiplicity.clear(); if(fStartCounters.empty() || fStartCounters.count(CounterTuple)) { fdEventStartTime = dDigiTime; } } fCounterMultiplicity[CounterTuple] |= 1 << iDigiCounterSide; if(fCounterORPartners.find(CounterTuple) != fCounterORPartners.end()) { for(auto const & CounterORPartner : fCounterORPartners.at(CounterTuple)) { fCounterMultiplicity[CounterORPartner] |= 1 << iDigiCounterSide; } } if(fInactiveCounterSides.find(CounterSideTuple) == fInactiveCounterSides.end()) { CbmTofDigiExp* tEventDigi(NULL); if(fbPreserveMCBacklinks) { // deep copy construction including 'CbmDigi::fMatch' tEventDigi = new((*fTofEventDigis)[fTofEventDigis->GetEntriesFast()]) CbmTofDigiExp(*tDigi); } else { // shallow construction excluding 'CbmDigi::fMatch' tEventDigi = new((*fTofEventDigis)[fTofEventDigis->GetEntriesFast()]) CbmTofDigiExp(iDigiAddress, dDigiTime, dDigiToT); } tEventDigi->SetTot(tEventDigi->GetTot() + fdDigiToTOffset); } } } } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- InitStatus CbmTofBuildDigiEvents::Init() { if(!FairRootManager::Instance()) { LOG(ERROR)<<"FairRootManager not found."<(FairRootManager::Instance()->GetSource()); if(!fFileSource) { LOG(ERROR)<<"Could not get pointer to FairFileSource."<(FairRootManager::Instance()->GetObject("TimeSlice.")); if(!fTimeSliceHeader) { if(!fbRealData) { LOG(ERROR)<<"Could not retrieve branch 'TimeSlice.' from FairRootManager."<(FairRootManager::Instance()->GetObject("TofDigiExp")); if(!fTofTimeSliceDigis) { LOG(ERROR)<<"Could not retrieve branch 'TofDigiExp' from FairRootManager."<(FairRootManager::Instance()->GetObject("MCEventList.")); if(!fInputMCEventList) { if(!fbRealData) { LOG(ERROR)<<"Could not retrieve branch 'MCEventList.' from FairRootManager."<GetObject("TofPointTB")) { LOG(ERROR)<<"Timeslice branch with MC points found. Event building would not work properly."<Register("EventList.", "EventList", fOutputMCEventList, IsOutputBranchPersistent("EventList.")); } fTofEventDigis = new TClonesArray("CbmTofDigiExp", 100); if(!fbRealData) { FairRootManager::Instance()->Register("CbmTofDigiExp", "TOF event digis", fTofEventDigis, IsOutputBranchPersistent("CbmTofDigiExp")); } else { FairRootManager::Instance()->Register("CbmTofDigi", "TOF event digis", fTofEventDigis, IsOutputBranchPersistent("CbmTofDigi")); } if(0. >= fdEventWindow) { fbMCEventBuilding = kTRUE; if(fbRealData) { LOG(ERROR)<<"Negative or zero width of the event building window requested for real data."<Delete(); fCounterMultiplicity.clear(); } } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofBuildDigiEvents::SetTriggerCounter(Int_t iModuleType, Int_t iModuleIndex, Int_t iCounterIndex, Int_t iNCounterSides, Int_t iCounterORGroup, Bool_t bIsStartCounter) { auto CounterTuple = std::make_tuple(iModuleType, iModuleIndex, iCounterIndex); fNominalTriggerCounterMultiplicity.emplace(CounterTuple, (1 == iNCounterSides) ? 1 : 3); if(-1 < iCounterORGroup) { auto & CounterORGroup = fCounterORGroups[iCounterORGroup]; CounterORGroup.emplace(CounterTuple); } if(bIsStartCounter) { fStartCounters.emplace(CounterTuple); } } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofBuildDigiEvents::ProcessIdealEvents(Double_t dProcessingTime) { for(auto itEvent = fIdealEventStartTimes.cbegin(); itEvent != fIdealEventStartTimes.cend(); ) { auto EventID = itEvent->first; Double_t dEventStartTime = itEvent->second; if(dProcessingTime - dEventStartTime > fdIdealEventWindow) { for(auto & tDigi : fIdealEventDigis.at(EventID)) { Int_t iDigiModuleType = tDigi->GetType(); Int_t iDigiModuleIndex = tDigi->GetSm(); Int_t iDigiCounterIndex = tDigi->GetRpc(); Int_t iDigiCounterSide = tDigi->GetSide(); auto CounterTuple = std::make_tuple(iDigiModuleType, iDigiModuleIndex, iDigiCounterIndex); auto CounterSideTuple = std::make_tuple(iDigiModuleType, iDigiModuleIndex, iDigiCounterIndex, iDigiCounterSide); fCounterMultiplicity[CounterTuple] |= 1 << iDigiCounterSide; if(fCounterORPartners.find(CounterTuple) != fCounterORPartners.end()) { for(auto const & CounterORPartner : fCounterORPartners.at(CounterTuple)) { fCounterMultiplicity[CounterORPartner] |= 1 << iDigiCounterSide; } } if(fInactiveCounterSides.find(CounterSideTuple) == fInactiveCounterSides.end()) { // deep copy construction including 'CbmDigi::fMatch' (only if already deep-copied in 'Exec') CbmTofDigiExp* tEventDigi = new((*fTofEventDigis)[fTofEventDigis->GetEntriesFast()]) CbmTofDigiExp(*tDigi); tEventDigi->SetTot(tEventDigi->GetTot() + fdDigiToTOffset); } delete tDigi; } std::map, UChar_t> ActualTriggerCounterMultiplicity; std::set_intersection(fCounterMultiplicity.begin(), fCounterMultiplicity.end(), fNominalTriggerCounterMultiplicity.begin(), fNominalTriggerCounterMultiplicity.end(), std::inserter(ActualTriggerCounterMultiplicity, ActualTriggerCounterMultiplicity.begin())); if(ActualTriggerCounterMultiplicity.size() >= fiTriggerMultiplicity) { if(fbPreserveMCBacklinks) { FillMCEventList(); } FairRootManager::Instance()->Fill(); fiNEvents++; fOutputMCEventList->Clear(""); fTofEventDigis->Delete(); } else { fTofEventDigis->Delete(); } fCounterMultiplicity.clear(); fIdealEventDigis.erase(EventID); fProcessedIdealEvents.emplace(EventID); itEvent = fIdealEventStartTimes.erase(itEvent); } else { ++itEvent; } } } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofBuildDigiEvents::FillMCEventList() { std::set> MCEventSet; for(Int_t iDigi = 0; iDigi < fTofEventDigis->GetEntriesFast(); iDigi++) { CbmTofDigiExp* tDigi = dynamic_cast(fTofEventDigis->At(iDigi)); Int_t iNMCLinks = tDigi->GetMatch()->GetNofLinks(); for(Int_t iLink = 0; iLink < iNMCLinks; iLink++) { const CbmLink& tLink = tDigi->GetMatch()->GetLink(iLink); Int_t iFileIndex = tLink.GetFile(); Int_t iEventIndex = tLink.GetEntry(); // Collect original MC event affiliations of digis attributed to // the current reconstructed event. if(-1 < iFileIndex && -1 < iEventIndex) { MCEventSet.emplace(iFileIndex, iEventIndex); } } } // Read the respective start times of the original MC events contributing to // the reconstructed event from the input MC event list and make them // available in the output MC event list. for(auto const & MCEvent : MCEventSet) { Int_t iFileIndex = MCEvent.first; Int_t iEventIndex = MCEvent.second; Double_t dStartTime = fInputMCEventList->GetEventTime(iEventIndex, iFileIndex); if(-1. != dStartTime) { fOutputMCEventList->Insert(iEventIndex, iFileIndex, dStartTime); } else { LOG(FATAL)<Sort(); } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofBuildDigiEvents::SetIgnoreCounterSide(Int_t iModuleType, Int_t iModuleIndex, Int_t iCounterIndex, Int_t iCounterSide) { fInactiveCounterSides.emplace(std::make_tuple(iModuleType, iModuleIndex, iCounterIndex, iCounterSide)); } // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- void CbmTofBuildDigiEvents::CompileCounterORPartners() { for(auto const & CounterORGroup : fCounterORGroups) { const auto & CounterORGroupMembers = CounterORGroup.second; for(auto const & CounterORGroupMember : CounterORGroupMembers) { for(auto const & CounterORGroupPartner : CounterORGroupMembers) { if(CounterORGroupMember != CounterORGroupPartner) { auto & CounterORGroupPartners = fCounterORPartners[CounterORGroupMember]; CounterORGroupPartners.emplace(CounterORGroupPartner); } } } } } // --------------------------------------------------------------------------- ClassImp(CbmTofBuildDigiEvents)