/******************************************************************************** * 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 "Cbm2021EventBuilderAlgo.h" /// CBM headers #include "CbmEvent.h" #include "CbmMuchBeamTimeDigi.h" #include "CbmMuchDigi.h" #include "CbmPsdDigi.h" #include "CbmRichDigi.h" #include "CbmStsDigi.h" #include "CbmTofDigi.h" #include "CbmTrdDigi.h" #include "TimesliceMetaData.h" /// FAIRROOT headers #include "FairLogger.h" #include "FairRootManager.h" #include "FairRunOnline.h" /// FAIRSOFT headers (geant, boost, ...) #include "TCanvas.h" #include "TClonesArray.h" #include "TH1.h" #include "TH2.h" #include "THttpServer.h" /// C/C++ headers // ---- Default constructor -------------------------------------------- Cbm2021EventBuilderAlgo::Cbm2021EventBuilderAlgo() {} // ---- Destructor ----------------------------------------------------- Cbm2021EventBuilderAlgo::~Cbm2021EventBuilderAlgo() {} // ---- Init ----------------------------------------------------------- Bool_t Cbm2021EventBuilderAlgo::InitAlgo() { LOG(info) << "Cbm2021EventBuilderAlgo::InitAlgo => Starting sequence"; // Get a handle from the IO manager FairRootManager* ioman = FairRootManager::Instance(); /// Check if reference detector data are available if (kFALSE == CheckDataAvailable(fRefDet)) { LOG(fatal) << "No digi input for reference detector, stopping there!"; } // if( kFALSE == CheckDataAvailable( fRefDet ) ) /// Check if data for detectors in selection list are available for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { if (kFALSE == CheckDataAvailable(*det)) { LOG(fatal) << "No digi input for one of selection detector, stopping there!"; } // if( kFALSE == CheckDataAvailable( *det ) ) } // for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) /// Access the TS metadata to know TS start time if needed if (fdTsStartTime < 0 || fdTsLength < 0 || fdTsOverLength < 0) { fTimeSliceMetaDataArray = dynamic_cast<TClonesArray*>(ioman->GetObject("TimesliceMetaData")); if (!fTimeSliceMetaDataArray) { LOG(fatal) << "No TS metadata input found" << " => Please check in the unpacking macro if the following line was " "present!" << std::endl << "source->SetWriteOutputFlag(kTRUE); // For writing TS metadata"; } // if (!fTimeSliceMetaDataArray) } // if ( fdTsStartTime < 0 || fdTsLength < 0 || fdTsOverLength < 0 ) if (fbFillHistos) { CreateHistograms(); } // if( fbFillHistos ) LOG(info) << "Cbm2021EventBuilderAlgo::InitAlgo => Done"; return kTRUE; } // ---- ProcessTs ------------------------------------------------------ void Cbm2021EventBuilderAlgo::ProcessTs() { LOG_IF(info, fuNrTs % 1000 == 0) << "Begin of TS " << fuNrTs; InitTs(); BuildEvents(); /// Store last event with trigger if not done by other seed if (nullptr != fCurrentEvent) { /// TODO: store start time of current event ? // fCurrentEvent->SetStartTime( fPrevTime ); // Replace Seed time with time of first digi in event? fCurrentEvent->SetEndTime(fdPrevEvtEndTime); fEventVector.push_back(fCurrentEvent); fuCurEv++; /// Prevent building over TS edge fCurrentEvent = nullptr; } // if( nullptr != fCurrentEvent ) LOG(debug) << "Found " << fEventVector.size() << " triggered events"; if (fbFillHistos) { FillHistos(); } // if( fbFillHistos ) fuNrTs++; } void Cbm2021EventBuilderAlgo::ClearEventVector() { /// Need to delete the object the pointer points to first int counter = 0; for (CbmEvent* event : fEventVector) { LOG(debug) << "Event " << counter << " has " << event->GetNofData() << " digis"; delete event; counter++; } // for( CbmEvent* event: fEventVector) fEventVector.clear(); } // ---- Finish --------------------------------------------------------- void Cbm2021EventBuilderAlgo::Finish() { LOG(info) << "Total errors: " << fuErrors; } // --------------------------------------------------------------------- Bool_t Cbm2021EventBuilderAlgo::CheckDataAvailable( EventBuilderDetector& det) { // Get a handle from the IO manager FairRootManager* ioman = FairRootManager::Instance(); if (ECbmModuleId::kT0 == det.detId) { // T0 is not included in DigiManager fT0DigiVec = ioman->InitObjectAs<std::vector<CbmTofDigi> const*>("T0Digi"); if (!fT0DigiVec) { LOG(info) << "No T0 digi input found."; return kFALSE; } } else if (ECbmModuleId::kSts == det.detId) { if (!fStsDigis) { LOG(info) << "No " << det.sName << " digi input found."; return kFALSE; } } else if (ECbmModuleId::kMuch == det.detId) { if (!fMuchDigis && !fMuchBeamTimeDigis ) { LOG(info) << "No " << det.sName << " digi input found."; return kFALSE; } } else if (ECbmModuleId::kTrd == det.detId) { if (!fTrdDigis) { LOG(info) << "No " << det.sName << " digi input found."; return kFALSE; } } else if (ECbmModuleId::kTof == det.detId) { if (!fTofDigis) { LOG(info) << "No " << det.sName << " digi input found."; return kFALSE; } } else if (ECbmModuleId::kRich == det.detId) { if (!fRichDigis) { LOG(info) << "No " << det.sName << " digi input found."; return kFALSE; } } else if (ECbmModuleId::kPsd == det.detId) { if (!fPsdDigis) { LOG(info) << "No " << det.sName << " digi input found."; return kFALSE; } } return kTRUE; } // --------------------------------------------------------------------- void Cbm2021EventBuilderAlgo::InitTs() { /// Reset TS based variables (analysis per TS = no building over the border) /// Reference detector fRefDet.fuStartIndex = 0; fRefDet.fuEndIndex = 0; /// Loop on detectors in selection list for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { (*det).fuStartIndex = 0; (*det).fuEndIndex = 0; } // for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) } void Cbm2021EventBuilderAlgo::BuildEvents() { /// Call LoopOnSeed with proper template argument switch (fRefDet.detId) { case ECbmModuleId::kSts: { LoopOnSeeds<CbmStsDigi>(); break; } // case ECbmModuleId::kSts: case ECbmModuleId::kMuch: { if (fbUseMuchBeamtimeDigi) { LoopOnSeeds<CbmMuchBeamTimeDigi>(); } // if (fbUseMuchBeamtimeDigi) else { LoopOnSeeds<CbmMuchDigi>(); } // else of if (fbUseMuchBeamtimeDigi) break; } // case ECbmModuleId::kMuch: case ECbmModuleId::kTrd: { LoopOnSeeds<CbmTrdDigi>(); break; } // case ECbmModuleId::kTrd: case ECbmModuleId::kTof: { LoopOnSeeds<CbmTofDigi>(); break; } // case ECbmModuleId::kTof: case ECbmModuleId::kRich: { LoopOnSeeds<CbmRichDigi>(); break; } // case ECbmModuleId::kRich: case ECbmModuleId::kPsd: { LoopOnSeeds<CbmPsdDigi>(); break; } // case ECbmModuleId::kPsd: case ECbmModuleId::kT0: { LoopOnSeeds<CbmTofDigi>(); break; } // case ECbmModuleId::kT0: default: { LOG(fatal) << "Cbm2021EventBuilderAlgo::BuildEvents => " << "Trying to search event seeds with unsupported det: " << fRefDet.sName; break; } // default: } // switch( *det ) } UInt_t Cbm2021EventBuilderAlgo::GetNofDigis( ECbmModuleId detId ) { switch (detId) { case ECbmModuleId::kSts: { return fStsDigis->size(); } case ECbmModuleId::kMuch: { if (fbUseMuchBeamtimeDigi) { return fMuchBeamTimeDigis->size(); } else { return fMuchDigis->size(); } } case ECbmModuleId::kTrd: { return fTrdDigis->size(); } case ECbmModuleId::kTof: { return fTofDigis->size(); } case ECbmModuleId::kRich: { return fRichDigis->size(); } case ECbmModuleId::kPsd: { return fPsdDigis->size(); } case ECbmModuleId::kT0: { return fT0DigiVec->size(); //what to do here? Not in digi manager. } default: { LOG(fatal) << "Cbm2021EventBuilderAlgo::GetNofDigis => " << "Trying to get digi number with unsupported detector."; return -1; } } } bool Cbm2021EventBuilderAlgo::DetIsPresent( ECbmModuleId detId ) { switch (detId) { case ECbmModuleId::kSts: { return fStsDigis!=nullptr; } case ECbmModuleId::kMuch: { if (fbUseMuchBeamtimeDigi) { return fMuchBeamTimeDigis!=nullptr; } else { return fMuchDigis!=nullptr; } } case ECbmModuleId::kTrd: { return fTrdDigis!=nullptr; } case ECbmModuleId::kTof: { return fTofDigis!=nullptr; } case ECbmModuleId::kRich: { return fRichDigis!=nullptr; } case ECbmModuleId::kPsd: { return fPsdDigis!=nullptr; } case ECbmModuleId::kT0: { return fT0DigiVec!=nullptr; //what to do here? Not in digi manager. } default: { LOG(fatal) << "Cbm2021EventBuilderAlgo::GetNofDigis => " << "Trying to get digi number with unsupported detector."; return -1; } } } template<> const CbmStsDigi* Cbm2021EventBuilderAlgo::GetDigi( UInt_t uDigi ) { return &((*fStsDigis)[uDigi]); } template<> const CbmMuchBeamTimeDigi* Cbm2021EventBuilderAlgo::GetDigi( UInt_t uDigi ) { return &((*fMuchBeamTimeDigis)[uDigi]); } template<> const CbmMuchDigi* Cbm2021EventBuilderAlgo::GetDigi( UInt_t uDigi ) { return &((*fMuchDigis)[uDigi]); } template<> const CbmTrdDigi* Cbm2021EventBuilderAlgo::GetDigi( UInt_t uDigi ) { return &((*fTrdDigis)[uDigi]); } template<> const CbmTofDigi* Cbm2021EventBuilderAlgo::GetDigi( UInt_t uDigi ) { return &((*fTofDigis)[uDigi]); } template<> const CbmRichDigi* Cbm2021EventBuilderAlgo::GetDigi( UInt_t uDigi ) { return &((*fRichDigis)[uDigi]); } template<> const CbmPsdDigi* Cbm2021EventBuilderAlgo::GetDigi( UInt_t uDigi ) { return &((*fPsdDigis)[uDigi]); } template<class DigiSeed> void Cbm2021EventBuilderAlgo::LoopOnSeeds() { /// Access the TS metadata if needed to know TS start time and overlap size Double_t dTsStartTime = fdTsStartTime; Double_t dOverlapStart = fdTsStartTime + fdTsLength; Double_t dOverlapSize = fdTsOverLength; if (fdTsStartTime < 0 || fdTsLength < 0 || fdTsOverLength < 0) { pTsMetaData = dynamic_cast<TimesliceMetaData*>(fTimeSliceMetaDataArray->At(0)); if (nullptr == pTsMetaData) LOG(fatal) << Form("Cbm2021EventBuilderAlgo::LoopOnSeeds => " "No TS metadata found for TS %6u.", fuNrTs); dTsStartTime = pTsMetaData->GetStartTime(); dOverlapStart = pTsMetaData->GetOverlapStartTime(); dOverlapSize = pTsMetaData->GetOverlapDuration(); } // if ( fdTsStartTime < 0 || fdTsLength < 0 || fdTsOverLength < 0 ) /// Print warning in first TS if time window borders out of potential overlap if ((0.0 < fdEarliestTimeWinBeg && dOverlapSize < fdLatestTimeWinEnd) || (dOverlapSize < fdWidestTimeWinRange)) { LOG(warning) << "Cbm2021EventBuilderAlgo::LoopOnSeeds => " << Form("Event window not fitting in TS overlap, risk of " "incomplete events: %f %f %f %f", fdEarliestTimeWinBeg, fdLatestTimeWinEnd, fdWidestTimeWinRange, dOverlapSize); } // if end of event window does not fit in overlap for a seed at edge of TS core /// Define an acceptance window for the seeds in order to use the overlap /// part of the TS to avoid incomplete events Double_t dSeedWindowBeg = dTsStartTime + (0.0 < fdEarliestTimeWinBeg ? 0.0 : -fdEarliestTimeWinBeg); Double_t dSeedWindowEnd = dOverlapStart + (0.0 < fdEarliestTimeWinBeg ? 0.0 : -fdEarliestTimeWinBeg); if (fbIgnoreTsOverlap) { dSeedWindowBeg = dTsStartTime; dSeedWindowEnd = dOverlapStart; } // if( fbIgnoreTsOverlap ) if (ECbmModuleId::kT0 == fRefDet.detId) { if (fT0DigiVec) { /// Loop on size of vector UInt_t uNbRefDigis = fT0DigiVec->size(); /// Loop on size of vector for (UInt_t uDigi = 0; uDigi < uNbRefDigis; ++uDigi) { LOG(debug) << Form("Checking seed %6u / %6u", uDigi, uNbRefDigis); Double_t dTime = fT0DigiVec->at(uDigi).GetTime(); /// Check Seed and build event if needed CheckSeed(dTime, uDigi); } // for( UInt_t uDigi = 0; uDigi < uNbRefDigis; ++uDigi ) } // if ( fT0DigiVec ) else LOG(fatal) << "Cbm2021EventBuilderAlgo::LoopOnSeeds => " << "T0 as reference detector but vector not found!"; } // if (ECbmModuleId::kT0 == fRefDet.detId) else { UInt_t uNbRefDigis = (0 < GetNofDigis(fRefDet.detId) ? GetNofDigis(fRefDet.detId) : 0); /// Loop on size of vector for (UInt_t uDigi = 0; uDigi < uNbRefDigis; ++uDigi) { LOG(debug) << Form("Checking seed %6u / %6u", uDigi, uNbRefDigis); const DigiSeed* pDigi = GetDigi<DigiSeed>(uDigi); /// Check that _entry is not out of range if (nullptr != pDigi) { Double_t dTime = pDigi->GetTime(); /// Check if seed in acceptance window if (dTime < dSeedWindowBeg) { continue; } // if( dTime < dSeedWindowBeg ) else if (dSeedWindowEnd < dTime) { break; } // else if( dSeedWindowEnd < dTime ) /// Check Seed and build event if needed CheckSeed(dTime, uDigi); } // if( nullptr != pDigi ) } // for( UInt_t uDigi = 0; uDigi < uNbRefDigis; ++uDigi ) } // else of if (ECbmModuleId::kT0 == fRefDet.detId) => Digi containers controlled by DigiManager } void Cbm2021EventBuilderAlgo::CheckSeed(Double_t dSeedTime, UInt_t uSeedDigiIdx) { /// If previous event valid and event overlap not allowed, check if we are in overlap /// and react accordingly if (nullptr != fCurrentEvent && (EOverlapMode::AllowOverlap != fOverMode || dSeedTime - fdPrevEvtTime < fRefDet.GetTimeWinRange()) && dSeedTime - fdPrevEvtTime < fdWidestTimeWinRange) { /// Within overlap range switch (fOverMode) { case EOverlapMode::NoOverlap: { /// No overlap allowed => reject LOG(debug1) << "Reject seed due to overlap"; return; break; } // case EOverlapMode::NoOverlap: case EOverlapMode::MergeOverlap: { /// Merge overlap mode => do nothing and go on filling current event break; } // case EOverlapMode::MergeOverlap: case EOverlapMode::AllowOverlap: { /// In allow overlap mode => reject only if reference det is in overlap /// to avoid cloning events due to single seed cluster LOG(debug1) << "Reject seed because part of cluster of previous one"; return; break; } // case EOverlapMode::AllowOverlap: } // switch( fOverMode ) } // if( prev Event exists and mode forbiden overlap present ) else { /// Out of overlap range or in overlap allowed mode /// => store previous event if not empty and create new one if (nullptr != fCurrentEvent) { /// TODO: store start time of current event ? // fCurrentEvent->SetStartTime( fPrevTime ); // Replace Seed time with time of first digi in event? fCurrentEvent->SetEndTime(fdPrevEvtEndTime); fEventVector.push_back(fCurrentEvent); fuCurEv++; } // if( nullptr != fCurrentEvent ) fCurrentEvent = new CbmEvent(fuCurEv, dSeedTime, 0.); } // else of if( prev Event exists and mode forbiden overlap present ) /// If window open for reference detector, search for other reference Digis matching it /// Otherwise only add the current seed if (fRefDet.fdTimeWinBeg < fRefDet.fdTimeWinEnd) { switch (fRefDet.detId) { case ECbmModuleId::kSts: { SearchMatches<CbmStsDigi>(dSeedTime, fRefDet); break; } // case ECbmModuleId::kSts: case ECbmModuleId::kMuch: { if (fbUseMuchBeamtimeDigi) { SearchMatches<CbmMuchBeamTimeDigi>(dSeedTime, fRefDet); } // if (fbUseMuchBeamtimeDigi) else { SearchMatches<CbmMuchDigi>(dSeedTime, fRefDet); } // else of if (fbUseMuchBeamtimeDigi) break; } // case ECbmModuleId::kMuch: case ECbmModuleId::kTrd: { SearchMatches<CbmTrdDigi>(dSeedTime, fRefDet); break; } // case ECbmModuleId::kTrd: case ECbmModuleId::kTof: { SearchMatches<CbmTofDigi>(dSeedTime, fRefDet); break; } // case ECbmModuleId::kTof: case ECbmModuleId::kRich: { SearchMatches<CbmRichDigi>(dSeedTime, fRefDet); break; } // case ECbmModuleId::kRich: case ECbmModuleId::kPsd: { SearchMatches<CbmPsdDigi>(dSeedTime, fRefDet); break; } // case ECbmModuleId::kPsd: case ECbmModuleId::kT0: { SearchMatches<CbmTofDigi>(dSeedTime, fRefDet); break; } // case ECbmModuleId::kT0: default: { LOG(fatal) << "Cbm2021EventBuilderAlgo::LoopOnSeeds => " << "Trying to search matches with unsupported det: " << fRefDet.sName << std::endl << "You may want to add support for it in the method."; break; } // default: } // switch( fRefDet ) /// Also add the seed if the window starts after the seed if (0 < fRefDet.fdTimeWinBeg) AddDigiToEvent(fRefDet, uSeedDigiIdx); } // if( fdRefTimeWinBeg < fdRefTimeWinEnd ) else { AddDigiToEvent(fRefDet, uSeedDigiIdx); } // else of if( fdRefTimeWinBeg < fdRefTimeWinEnd ) /// Search for matches for each detector in selection list for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { switch ((*det).detId) { case ECbmModuleId::kSts: { SearchMatches<CbmStsDigi>(dSeedTime, *det); break; } // case ECbmModuleId::kSts: case ECbmModuleId::kMuch: { if (fbUseMuchBeamtimeDigi) { SearchMatches<CbmMuchBeamTimeDigi>(dSeedTime, *det); } // if (fbUseMuchBeamtimeDigi) else { SearchMatches<CbmMuchDigi>(dSeedTime, *det); } // else of if (fbUseMuchBeamtimeDigi) break; } // case ECbmModuleId::kMuch: case ECbmModuleId::kTrd: { SearchMatches<CbmTrdDigi>(dSeedTime, *det); break; } // case ECbmModuleId::kTrd: case ECbmModuleId::kTof: { SearchMatches<CbmTofDigi>(dSeedTime, *det); break; } // case ECbmModuleId::kTof: case ECbmModuleId::kRich: { SearchMatches<CbmRichDigi>(dSeedTime, *det); break; } // case ECbmModuleId::kRich: case ECbmModuleId::kPsd: { SearchMatches<CbmPsdDigi>(dSeedTime, *det); break; } // case ECbmModuleId::kPsd: case ECbmModuleId::kT0: { SearchMatches<CbmTofDigi>(dSeedTime, *det); break; } // case ECbmModuleId::kT0: default: { LOG(fatal) << "Cbm2021EventBuilderAlgo::LoopOnSeeds => " << "Trying to search matches with unsupported det: " << (*det).sName << std::endl << "You may want to add support for it in the method."; break; } // default: } // switch( *det ) } // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det ) /// Check if event is filling trigger conditions and clear it if not if (HasTrigger(fCurrentEvent)) { fdPrevEvtTime = dSeedTime; /// In case of NoOverlap or MergeOverlap, we can and should start checking the next window /// from end of current window in order to save CPU and avoid duplicating if (EOverlapMode::NoOverlap == fOverMode || EOverlapMode::MergeOverlap == fOverMode) { /// Update reference detector fRefDet.fuStartIndex = fRefDet.fuEndIndex; /// Loop on selection detectors for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { (*det).fuStartIndex = (*det).fuEndIndex; } // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det ) } // If no overlap or merge overlap } // if( !HasTrigger( fCurrentEvent ) ) else { LOG(debug1) << "Reject seed due to Trigger requirements"; delete fCurrentEvent; fCurrentEvent = nullptr; /// delete does NOT set a pointer to nullptr... } // else of if( !HasTrigger( fCurrentEvent ) ) } template<class DigiCheck> void Cbm2021EventBuilderAlgo::SearchMatches( Double_t dSeedTime, EventBuilderDetector& detMatch) { /// This algo relies on time sorted vectors for the selected detectors UInt_t uLocalIndexStart = detMatch.fuStartIndex; UInt_t uLocalIndexEnd = detMatch.fuStartIndex; /// Check the Digis until out of window if (ECbmModuleId::kT0 == detMatch.detId) { if (fT0DigiVec) { /// Loop on size of vector UInt_t uNbSelDigis = fT0DigiVec->size(); /// Loop on size of vector for (UInt_t uDigi = detMatch.fuStartIndex; uDigi < uNbSelDigis; ++uDigi) { Double_t dTime = fT0DigiVec->at(uDigi).GetTime(); Double_t dTimeDiff = dTime - dSeedTime; /// Check if within time window, update start/stop indices if needed if (dTimeDiff < detMatch.fdTimeWinBeg) { ++uLocalIndexStart; continue; } // if( dTimeDiff < detMatch.fdTimeWinBeg ) else if (detMatch.fdTimeWinEnd < dTimeDiff) { /// Store as end the first digi out of window to avoid double counting in case of /// merged overlap event mode uLocalIndexEnd = uDigi; break; } // else if( detMatch.fdTimeWinEnd < dTimeDiff ) of if( dTimeDiff < detMatch.fdTimeWinBeg ) AddDigiToEvent(detMatch, uDigi); if (fdPrevEvtEndTime < dTime) fdPrevEvtEndTime = dTime; } // for( UInt_t uDigi = 0; uDigi < uNbSelDigis; ++uDigi ) /// catch the case where we reach the end of the vector before being out of the time window if (uLocalIndexEnd < uLocalIndexStart) uLocalIndexEnd = uNbSelDigis; } // if ( fT0DigiVec ) else LOG(fatal) << "Cbm2021EventBuilderAlgo::SearchMatches => " << "T0 as selection detector but vector not found!"; } // if( ECbmModuleId::kT0 == detMatch.detId ) else { UInt_t uNbSelDigis = (0 < GetNofDigis(detMatch.detId) ? GetNofDigis(detMatch.detId) : 0); /// Loop on size of vector for (UInt_t uDigi = detMatch.fuStartIndex; uDigi < uNbSelDigis; ++uDigi) { const DigiCheck* pDigi = GetDigi<DigiCheck>(uDigi); /// Check that _entry is not out of range if (nullptr != pDigi) { Double_t dTime = pDigi->GetTime(); Double_t dTimeDiff = dTime - dSeedTime; LOG(debug4) << detMatch.sName << Form(" => Checking match %6u / %6u, dt %f", uDigi, uNbSelDigis, dTimeDiff); /// Check if within time window, update start/stop indices if needed if (dTimeDiff < detMatch.fdTimeWinBeg) { ++uLocalIndexStart; continue; } // if( dTimeDiff < detMatch.fdTimeWinBeg ) else if (detMatch.fdTimeWinEnd < dTimeDiff) { /// Store as end the first digi out of window to avoid double counting in case of /// merged overlap event mode uLocalIndexEnd = uDigi; break; } // else if( detMatch.fdTimeWinEnd < dTimeDiff ) of if( dTimeDiff < detMatch.fdTimeWinBeg ) AddDigiToEvent(detMatch, uDigi); if (fdPrevEvtEndTime < dTime) fdPrevEvtEndTime = dTime; } // if( nullptr != pDigi ) } // for( UInt_t uDigi = 0; uDigi < uNbSelDigis; ++uDigi ) /// catch the case where we reach the end of the vector before being out of the time window if (uLocalIndexEnd < uLocalIndexStart) uLocalIndexEnd = uNbSelDigis; } // else of if( ECbmModuleId::kT0 == detMatch.detId ) => Digi containers controlled by DigiManager /// Update the StartIndex and EndIndex for the next event seed detMatch.fuStartIndex = uLocalIndexStart; detMatch.fuEndIndex = uLocalIndexEnd; } void Cbm2021EventBuilderAlgo::AddDigiToEvent( EventBuilderDetector& det, Int_t _entry) { fCurrentEvent->AddData(det.dataType, _entry); } Bool_t Cbm2021EventBuilderAlgo::HasTrigger(CbmEvent* event) { /// Check first reference detector if (kFALSE == CheckTriggerConditions(event, fRefDet)) { return kFALSE; } // if (kFALSE == CheckTriggerConditions(event, fRefDet) ) /// Loop on selection detectors for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { if (kFALSE == CheckTriggerConditions(event, *det)) return kFALSE; } // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det ) /// All Ok, trigger is there return kTRUE; } Bool_t Cbm2021EventBuilderAlgo::CheckTriggerConditions( CbmEvent* event, EventBuilderDetector& det) { /// Check if both Trigger conditions disabled for this detector if (0 == det.fuTriggerMinDigis && det.fiTriggerMaxDigis < 0) { return kTRUE; } // if( 0 == det.fuTriggerMinDigis && det.fiTriggerMaxDigis < 0 ) /// Check if detector present if (ECbmModuleId::kT0 == det.detId) { /// FIXME: special case to be removed once T0 supported by DigiManager if (!(fT0DigiVec)) { LOG(warning) << "Event does not have digis storage for T0" << " while the following trigger minimum are defined: " << det.fuTriggerMinDigis << " " << det.fiTriggerMaxDigis; return kFALSE; } // if( !(fT0DigiVec) ) } // if( ECbmDataType::kT0Digi == det.detId ) else { if (!DetIsPresent(det.detId)) { LOG(warning) << "Event does not have digis storage for " << det.sName << " while the following trigger min/max are defined: " << det.fuTriggerMinDigis << " " << det.fiTriggerMaxDigis; return kFALSE; } // if( !fDigiMan->IsPresent( det ) ) } // else of if( ECbmDataType::kT0Digi == det ) /// Check trigger rejection by minimal number or absence Int_t iNbDigis = event->GetNofData(det.dataType); if ((-1 == iNbDigis) || (static_cast<UInt_t>(iNbDigis) < det.fuTriggerMinDigis)) { LOG(debug2) << "Event does not have enough digis: " << iNbDigis << " vs " << det.fuTriggerMinDigis << " for " << det.sName; return kFALSE; } // if((-1 == iNbDigis) || (static_cast<UInt_t>(iNbDigis) < det.fuTriggerMinDigis)) /// Check trigger rejection by maximal number else if (0 < det.fiTriggerMaxDigis && det.fiTriggerMaxDigis < iNbDigis) { LOG(debug2) << "Event Has too many digis: " << iNbDigis << " vs " << det.fiTriggerMaxDigis << " for " << det.sName; return kFALSE; } // else if( iNbDigis < det.fiTriggerMaxDigis ) else { return kTRUE; } // else of else if( iNbDigis < det.fiTriggerMaxDigis ) } //---------------------------------------------------------------------- void Cbm2021EventBuilderAlgo::CreateHistograms() { /// FIXME: Disable clang formatting for histograms declaration for now /* clang-format off */ fhEventTime = new TH1F("hEventTime", "seed time of the events; Seed time [s]; Events", 60000, 0, 600); fhEventDt = new TH1F( "fhEventDt", "interval in seed time of consecutive events; Seed time [s]; Events", 2100, -100.5, 1999.5); fhEventSize = new TH1F("hEventSize", "nb of all digis in the event; Nb Digis []; Events []", 10000, 0, 10000); fhNbDigiPerEvtTime = new TH2I("hNbDigiPerEvtTime", "nb of all digis per event vs seed time of the events; Seed time " "[s]; Nb Digis []; Events []", 600, 0, 600, 1000, 0, 10000); /// Loop on selection detectors for (std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { /// In case name not provided, do not create the histo to avoid name conflicts! if( "Invalid" == (*det).sName ) { fvhNbDigiPerEvtTimeDet.push_back( nullptr ); continue; } // if( "Invalid" == (*det).sName ) fvhNbDigiPerEvtTimeDet.push_back( new TH2I( Form( "hNbDigiPerEvtTime%s", (*det).sName.data() ), Form( "nb of %s digis per event vs seed time of the events; Seed time " "[s]; Nb Digis []; Events []", (*det).sName.data() ), 600, 0, 600, 4000, 0, 4000) ); } // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det ) AddHistoToVector(fhEventTime, "evtbuild"); AddHistoToVector(fhEventDt, "evtbuild"); AddHistoToVector(fhEventSize, "evtbuild"); AddHistoToVector(fhNbDigiPerEvtTime, "evtbuild"); for (std::vector<TH2*>::iterator itHist = fvhNbDigiPerEvtTimeDet.begin(); itHist != fvhNbDigiPerEvtTimeDet.end(); ++itHist) { if( nullptr != (*itHist) ) { AddHistoToVector((*itHist), "evtbuild"); } // if( nullptr != (*itHist) ) } // for( std::vector<TH2*>::iterator itHist = fvhNbDigiPerEvtTimeDet.begin(); itHist != fvhNbDigiPerEvtTimeDet.end(); ++itHist ) /// FIXME: Re-enable clang formatting after histograms declaration /* clang-format on */ } void Cbm2021EventBuilderAlgo::FillHistos() { Double_t dPreEvtTime = -1.0; for (CbmEvent* evt : fEventVector) { fhEventTime->Fill(evt->GetStartTime() * 1e-9); if (0.0 <= dPreEvtTime) { fhEventDt->Fill(evt->GetStartTime() - dPreEvtTime); } // if( 0.0 <= dPreEvtTime ) fhEventSize->Fill(evt->GetNofData()); fhNbDigiPerEvtTime->Fill(evt->GetStartTime() * 1e-9, evt->GetNofData()); /// Loop on selection detectors for (UInt_t uDetIdx = 0; uDetIdx < fvDets.size(); ++uDetIdx) { if (nullptr == fvhNbDigiPerEvtTimeDet[uDetIdx]) continue; fvhNbDigiPerEvtTimeDet[uDetIdx]->Fill( evt->GetStartTime() * 1e-9, evt->GetNofData(fvDets[uDetIdx].dataType)); } // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det ) dPreEvtTime = evt->GetStartTime(); } // for( CbmEvent * evt: fEventVector ) } void Cbm2021EventBuilderAlgo::ResetHistograms( Bool_t /*bResetTime*/) { fhEventTime->Reset(); fhEventDt->Reset(); fhEventSize->Reset(); fhNbDigiPerEvtTime->Reset(); /// Loop on histograms for (std::vector<TH2*>::iterator itHist = fvhNbDigiPerEvtTimeDet.begin(); itHist != fvhNbDigiPerEvtTimeDet.end(); ++itHist) { (*itHist)->Reset(); } // for( std::vector<TH2*>::iterator itHist = fvhNbDigiPerEvtTimeDet.begin(); itHist != fvhNbDigiPerEvtTimeDet.end(); ++itHist ) /* if( kTRUE == bResetTime ) { /// Also reset the Start time for the evolution plots! fdStartTime = -1.0; } // if( kTRUE == bResetTime ) */ } //---------------------------------------------------------------------- void Cbm2021EventBuilderAlgo::SetReferenceDetector( ECbmModuleId refDet, ECbmDataType dataTypeIn, std::string sNameIn, UInt_t uTriggerMinDigisIn, Int_t iTriggerMaxDigisIn, Double_t fdTimeWinBegIn, Double_t fdTimeWinEndIn) { /// FIXME: Deprecated method to be removed later. For now create temp object. SetReferenceDetector(EventBuilderDetector(refDet, dataTypeIn, sNameIn, uTriggerMinDigisIn, iTriggerMaxDigisIn, fdTimeWinBegIn, fdTimeWinEndIn)); } void Cbm2021EventBuilderAlgo::AddDetector(ECbmModuleId selDet, ECbmDataType dataTypeIn, std::string sNameIn, UInt_t uTriggerMinDigisIn, Int_t iTriggerMaxDigisIn, Double_t fdTimeWinBegIn, Double_t fdTimeWinEndIn) { /// FIXME: Deprecated method to be removed later. For now create temp object. AddDetector(EventBuilderDetector(selDet, dataTypeIn, sNameIn, uTriggerMinDigisIn, iTriggerMaxDigisIn, fdTimeWinBegIn, fdTimeWinEndIn)); } //---------------------------------------------------------------------- //---------------------------------------------------------------------- void Cbm2021EventBuilderAlgo::SetReferenceDetector( EventBuilderDetector refDetIn) { /// Loop on selection detectors for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { if ((*det) == refDetIn) { LOG(warning) << "Cbm2021EventBuilderAlgo::SetReferenceDetector => " "Reference detector already in selection detector list!" << refDetIn.sName; LOG(warning) << " => " "It will be automatically removed from selection detector list!"; LOG(warning) << " => " "Please also remember to update the selection windows to store " "clusters!"; RemoveDetector(refDetIn); } // if( (*det) == refDetIn ) } // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det ) if (fRefDet == refDetIn) { LOG(warning) << "Cbm2021EventBuilderAlgo::SetReferenceDetector => " "Doing nothing, identical reference detector already in use"; } // if( fRefDet == refDetIn ) else { LOG(info) << "Cbm2021EventBuilderAlgo::SetReferenceDetector => " << "Replacing " << fRefDet.sName << " with " << refDetIn.sName << " as reference detector"; LOG(warning) << " => " "You may want to use AddDetector after this command to add in " "selection " << refDetIn.sName; LOG(warning) << " => " "Please also remember to update the selection windows!"; } // else of if( fRefDet == refDetIn ) fRefDet = refDetIn; /// Update the variables storing the earliest and latest time window boundaries UpdateTimeWinBoundariesExtrema(); /// Update the variable storing the size if widest time window for overlap detection UpdateWidestTimeWinRange(); } void Cbm2021EventBuilderAlgo::AddDetector( EventBuilderDetector selDet) { if (fRefDet == selDet) { LOG(fatal) << "Cbm2021EventBuilderAlgo::AddDetector => Cannot " "add the reference detector as selection detector!" << std::endl << "=> Maybe first change the reference detector with " "SetReferenceDetector?"; } // if( fRefDet == selDet ) /// Loop on selection detectors for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { if ((*det) == selDet) { LOG(warning) << "Cbm2021EventBuilderAlgo::AddDetector => " "Doing nothing, selection detector already in list!" << selDet.sName; return; } // if( (*det) == selDet ) } // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det ) fvDets.push_back(selDet); /// Update the variables storing the earliest and latest time window boundaries UpdateTimeWinBoundariesExtrema(); /// Update the variable storing the size if widest time window for overlap detection UpdateWidestTimeWinRange(); } void Cbm2021EventBuilderAlgo::RemoveDetector( EventBuilderDetector selDet) { /// Loop on selection detectors for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { if ((*det) == selDet) { fvDets.erase(det); return; } // if( (*det) == selDet ) } // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det ) LOG(warning) << "Cbm2021EventBuilderAlgo::RemoveDetector => Doing " "nothing, selection detector not in list!" << selDet.sName; } //---------------------------------------------------------------------- void Cbm2021EventBuilderAlgo::SetTriggerMinNumber( ECbmModuleId selDet, UInt_t uVal) { /// Check first if reference detector if (fRefDet.detId == selDet) { fRefDet.fuTriggerMinDigis = uVal; LOG(debug) << "Set Trigger min limit for " << fRefDet.sName << " to " << uVal; return; } // if( fRefDet == selDet ) /// Loop on selection detectors for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { if ((*det).detId == selDet) { (*det).fuTriggerMinDigis = uVal; LOG(debug) << "Set Trigger min limit for " << (*det).sName << " to " << uVal; return; } // if( (*det).detId == selDet ) } // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det ) LOG(warning) << "Cbm2021EventBuilderAlgo::SetTriggerMinNumber => " "Doing nothing, detector neither reference nor in selection list!" << selDet; } void Cbm2021EventBuilderAlgo::SetTriggerMaxNumber( ECbmModuleId selDet, Int_t iVal) { /// Check first if reference detector if (fRefDet.detId == selDet) { fRefDet.fiTriggerMaxDigis = iVal; LOG(debug) << "Set Trigger min limit for " << fRefDet.sName << " to " << iVal; return; } // if( fRefDet == selDet ) /// Loop on selection detectors for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { if ((*det).detId == selDet) { (*det).fiTriggerMaxDigis = iVal; LOG(debug) << "Set Trigger min limit for " << (*det).sName << " to " << iVal; return; } // if( (*det).detId == selDet ) } // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det ) LOG(warning) << "Cbm2021EventBuilderAlgo::SetTriggerMaxNumber => " "Doing nothing, detector neither reference nor in selection list!" << selDet; } void Cbm2021EventBuilderAlgo::SetTriggerWindow(ECbmModuleId selDet, Double_t dWinBeg, Double_t dWinEnd) { /// Check if valid time window: end strictly after beginning if (dWinEnd <= dWinBeg) LOG(fatal) << "Cbm2021EventBuilderAlgo::SetTriggerWindow => " "Invalid time window: [ " << dWinBeg << ", " << dWinEnd << " ]"; Bool_t bFound = kFALSE; /// Check first if reference detector if (fRefDet.detId == selDet) { fRefDet.fdTimeWinBeg = dWinBeg; fRefDet.fdTimeWinEnd = dWinEnd; bFound = kTRUE; } // if( fRefDet == selDet ) /// Loop on selection detectors for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { if ((*det).detId == selDet) { (*det).fdTimeWinBeg = dWinBeg; (*det).fdTimeWinEnd = dWinEnd; bFound = kTRUE; } // if( (*det).detId == selDet ) } // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det ) if (kFALSE == bFound) { LOG(warning) << "Cbm2021EventBuilderAlgo::SetTriggerWindow => " "Doing nothing, detector neither reference nor in selection list!" << selDet; } // if( kFALSE == bFound ) /// Update the variables storing the earliest and latest time window boundaries UpdateTimeWinBoundariesExtrema(); /// Update the variable storing the size if widest time window for overlap detection UpdateWidestTimeWinRange(); } void Cbm2021EventBuilderAlgo::UpdateTimeWinBoundariesExtrema() { /// Initialize with reference detector fdEarliestTimeWinBeg = fRefDet.fdTimeWinBeg; fdLatestTimeWinEnd = fRefDet.fdTimeWinEnd; /// Loop on selection detectors for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { fdEarliestTimeWinBeg = std::min(fdEarliestTimeWinBeg, (*det).fdTimeWinBeg); fdLatestTimeWinEnd = std::max(fdLatestTimeWinEnd, (*det).fdTimeWinEnd); } // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det ) } void Cbm2021EventBuilderAlgo::UpdateWidestTimeWinRange() { /// Initialize with reference detector fdWidestTimeWinRange = fRefDet.fdTimeWinEnd - fRefDet.fdTimeWinBeg; /// Loop on selection detectors for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) { fdWidestTimeWinRange = std::max(fdWidestTimeWinRange, (*det).fdTimeWinEnd - (*det).fdTimeWinBeg); } // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det ) } //---------------------------------------------------------------------- ClassImp(Cbm2021EventBuilderAlgo)