diff --git a/reco/eventbuilder/digis/Cbm2021EventBuilderAlgo.cxx b/reco/eventbuilder/digis/Cbm2021EventBuilderAlgo.cxx new file mode 100644 index 0000000000000000000000000000000000000000..774ea4363ca53f45fdf9a56b153554e730796ac8 --- /dev/null +++ b/reco/eventbuilder/digis/Cbm2021EventBuilderAlgo.cxx @@ -0,0 +1,1107 @@ +/******************************************************************************** + * 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) diff --git a/reco/eventbuilder/digis/Cbm2021EventBuilderAlgo.h b/reco/eventbuilder/digis/Cbm2021EventBuilderAlgo.h new file mode 100644 index 0000000000000000000000000000000000000000..f132b866974b0f667ff9e41940ea5e7030afba75 --- /dev/null +++ b/reco/eventbuilder/digis/Cbm2021EventBuilderAlgo.h @@ -0,0 +1,337 @@ +/******************************************************************************** + * 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" * + ********************************************************************************/ +#ifndef CBM2021EVENTBUILDERALGO_H +#define CBM2021EVENTBUILDERALGO_H + +/// CBM headers +#include "CbmMuchBeamTimeDigi.h" +#include "CbmMuchDigi.h" +#include "CbmPsdDigi.h" +#include "CbmRichDigi.h" +#include "CbmStsDigi.h" +#include "CbmTofDigi.h" +#include "CbmTrdDigi.h" + +/// FAIRROOT headers +#include "FairTask.h" + +/// FAIRSOFT headers (geant, boost, ...) + +/// C/C++ headers +#include <array> +#include <map> +#include <set> +#include <tuple> +#include <vector> + +#include <boost/any.hpp> + +class TimesliceMetaData; +class CbmEvent; +class TClonesArray; +class TH1; +class TH2; +class TNamed; +class TCanvas; + +enum class EOverlapMode { NoOverlap, MergeOverlap, AllowOverlap }; + +class EventBuilderDetector { +public: + EventBuilderDetector() { ; } + EventBuilderDetector(ECbmModuleId detIdIn, + ECbmDataType dataTypeIn, + std::string sNameIn) { + detId = detIdIn; + dataType = dataTypeIn; + sName = sNameIn; + } + EventBuilderDetector(ECbmModuleId detIdIn, + ECbmDataType dataTypeIn, + std::string sNameIn, + UInt_t uTriggerMinDigisIn, + Int_t iTriggerMaxDigisIn, + Double_t fdTimeWinBegIn, + Double_t fdTimeWinEndIn) + : EventBuilderDetector(detIdIn, dataTypeIn, sNameIn) { + fuTriggerMinDigis = uTriggerMinDigisIn; + fiTriggerMaxDigis = iTriggerMaxDigisIn; + + fdTimeWinBeg = fdTimeWinBegIn; + fdTimeWinEnd = fdTimeWinEndIn; + } + + bool operator==(const EventBuilderDetector& other) const { + return (other.detId == this->detId); + } + bool operator!=(const EventBuilderDetector& other) const { + return (other.detId != this->detId); + } + + Double_t GetTimeWinRange() { return fdTimeWinEnd - fdTimeWinBeg; } + + /// Settings + ECbmModuleId detId = ECbmModuleId::kNotExist; + ECbmDataType dataType = ECbmDataType::kUnknown; + std::string sName = "Invalid"; + /// Minimum number of T0 digis needed to generate a trigger, 0 means don't use for trigger generation + UInt_t fuTriggerMinDigis = 0; + /// Maximum number of digis per detector to generate an event, -1 means no cut, 0 means anti-coinc trigger + Int_t fiTriggerMaxDigis = -1; + /// Selection Window + Double_t fdTimeWinBeg = -100; + Double_t fdTimeWinEnd = 100; + + /// Book-keeping variables + UInt_t fuStartIndex = 0; + UInt_t fuEndIndex = 0; +}; + +/// Pre-defined detector types +static const EventBuilderDetector kEventBuilderDetSts = + EventBuilderDetector(ECbmModuleId::kSts, ECbmDataType::kStsDigi, "Sts"); +static const EventBuilderDetector kEventBuilderDetMuch = + EventBuilderDetector(ECbmModuleId::kMuch, ECbmDataType::kMuchDigi, "Much"); +static const EventBuilderDetector kEventBuilderDetTrd = + EventBuilderDetector(ECbmModuleId::kTrd, ECbmDataType::kTrdDigi, "Trd"); +static const EventBuilderDetector kEventBuilderDetTof = + EventBuilderDetector(ECbmModuleId::kTof, ECbmDataType::kTofDigi, "Tof"); +static const EventBuilderDetector kEventBuilderDetRich = + EventBuilderDetector(ECbmModuleId::kRich, ECbmDataType::kRichDigi, "Rich"); +static const EventBuilderDetector kEventBuilderDetPsd = + EventBuilderDetector(ECbmModuleId::kPsd, ECbmDataType::kPsdDigi, "Psd"); +static const EventBuilderDetector kEventBuilderDetT0 = + EventBuilderDetector(ECbmModuleId::kT0, ECbmDataType::kT0Digi, "T0"); +static const EventBuilderDetector kEventBuilderDetUndef = + EventBuilderDetector(); + +class Cbm2021EventBuilderAlgo { +public: + /** Default constructor **/ + Cbm2021EventBuilderAlgo(); + + Cbm2021EventBuilderAlgo( + const Cbm2021EventBuilderAlgo&) = delete; + Cbm2021EventBuilderAlgo + operator=(const Cbm2021EventBuilderAlgo&) = delete; + + /** Destructor **/ + ~Cbm2021EventBuilderAlgo(); + + /** Initiliazation at the beginning of a run **/ + Bool_t InitAlgo(); + + /** Executed for each TS. **/ + void ProcessTs(); + + /** Finish called at the end of the run **/ + void Finish(); + + void SetFillHistos(Bool_t var) { fbFillHistos = var; } + void ResetHistograms(Bool_t bResetTime = kTRUE); + + void SetReferenceDetector(ECbmModuleId refDet, + ECbmDataType dataTypeIn, + std::string sNameIn, + UInt_t uTriggerMinDigisIn = 0, + Int_t iTriggerMaxDigisIn = -1, + Double_t fdTimeWinBegIn = -100, + Double_t fdTimeWinEndIn = 100); + void AddDetector(ECbmModuleId selDet, + ECbmDataType dataTypeIn, + std::string sNameIn, + UInt_t uTriggerMinDigisIn = 0, + Int_t iTriggerMaxDigisIn = -1, + Double_t fdTimeWinBegIn = -100, + Double_t fdTimeWinEndIn = 100); + + void SetReferenceDetector(EventBuilderDetector refDetIn); + void AddDetector(EventBuilderDetector selDet); + void RemoveDetector(EventBuilderDetector selDet); + + void SetTriggerMinNumber(ECbmModuleId selDet, UInt_t uVal); + void SetTriggerMaxNumber(ECbmModuleId selDet, Int_t iVal); + + void + SetTriggerWindow(ECbmModuleId selDet, Double_t dWinBeg, Double_t dWinEnd); + + void SetTsParameters(Double_t dTsStartTime, + Double_t dTsLength, + Double_t dTsOverLength) { + fdTsStartTime = dTsStartTime; + fdTsLength = dTsLength; + fdTsOverLength = dTsOverLength; + } + + /// Control flags + void SetEventOverlapMode(EOverlapMode mode) { fOverMode = mode; } + void SetIgnoreTsOverlap(Bool_t bFlagIn = kTRUE) { + fbIgnoreTsOverlap = bFlagIn; + } + + void ChangeMuchBeamtimeDigiFlag(Bool_t bFlagIn = kFALSE) { + fbUseMuchBeamtimeDigi = bFlagIn; + } + + /// For monitor algos + void AddHistoToVector(TNamed* pointer, std::string sFolder = "") { + fvpAllHistoPointers.push_back( + std::pair<TNamed*, std::string>(pointer, sFolder)); + } + std::vector<std::pair<TNamed*, std::string>> GetHistoVector() { + return fvpAllHistoPointers; + } + void AddCanvasToVector(TCanvas* pointer, std::string sFolder = "") { + fvpAllCanvasPointers.push_back( + std::pair<TCanvas*, std::string>(pointer, sFolder)); + } + std::vector<std::pair<TCanvas*, std::string>> GetCanvasVector() { + return fvpAllCanvasPointers; + } + + /// Set digi containers + void SetStsDigis( std::vector<CbmStsDigi>* StsDigis ){ + fStsDigis = StsDigis; + } + void SetMuchDigis( std::vector<CbmMuchDigi>* MuchDigis ){ + fMuchDigis = MuchDigis; + } + void SetTrdDigis( std::vector<CbmTrdDigi>* TrdDigis ){ + fTrdDigis = TrdDigis; + } + void SetTofDigis( std::vector<CbmTofDigi>* TofDigis ){ + fTofDigis = TofDigis; + } + void SetRichDigis( std::vector<CbmRichDigi>* RichDigis ){ + fRichDigis = RichDigis; + } + void SetPsdDigis( std::vector<CbmPsdDigi>* PsdDigis ){ + fPsdDigis = PsdDigis; + } + void SetMuchBeamTimeDigis( std::vector<CbmMuchBeamTimeDigi>* MuchBeamTimeDigis ){ + fMuchBeamTimeDigis = MuchBeamTimeDigis; + } + + /// Data output access + std::vector<CbmEvent*>& GetEventVector() { return fEventVector; } + void ClearEventVector(); + +private: + /// Internal methods + Bool_t CheckDataAvailable(EventBuilderDetector& det); + void InitTs(); + void BuildEvents(); + + void CreateHistograms(); + void FillHistos(); + + template<class DigiSeed> + void LoopOnSeeds(); + void CheckSeed(Double_t dSeedTime, UInt_t uSeedDigiIdx); + template<class DigiCheck> + void SearchMatches(Double_t dSeedTime, EventBuilderDetector& detMatch); + void AddDigiToEvent(EventBuilderDetector& det, Int_t uIdx); + Bool_t HasTrigger(CbmEvent*); + Bool_t CheckTriggerConditions(CbmEvent* event, EventBuilderDetector& det); + + void UpdateTimeWinBoundariesExtrema(); + void UpdateWidestTimeWinRange(); + + /// Constants + static constexpr Double_t kdDefaultTimeWinBeg = -100.0; + static constexpr Double_t kdDefaultTimeWinEnd = 100.0; + + /// User parameters + /// Control flags + Bool_t fbIgnoreTsOverlap = kFALSE; //! Ignore data in Overlap part of the TS + Bool_t fbFillHistos {kTRUE}; //! Switch ON/OFF filling of histograms + Bool_t fbUseMuchBeamtimeDigi = kTRUE; //! Switch between MUCH digi classes + /// Event building mode and detectors selection + EOverlapMode fOverMode {EOverlapMode::AllowOverlap}; + + EventBuilderDetector fRefDet = + EventBuilderDetector(ECbmModuleId::kT0, ECbmDataType::kT0Digi, "T0"); + std::vector<EventBuilderDetector> fvDets = { + EventBuilderDetector(ECbmModuleId::kSts, ECbmDataType::kStsDigi, "kSts"), + EventBuilderDetector(ECbmModuleId::kMuch, ECbmDataType::kMuchDigi, "kMuch"), + EventBuilderDetector(ECbmModuleId::kTrd, ECbmDataType::kTrdDigi, "kTrd"), + EventBuilderDetector(ECbmModuleId::kTof, ECbmDataType::kTofDigi, "kTof"), + EventBuilderDetector(ECbmModuleId::kRich, ECbmDataType::kRichDigi, "kRich"), + EventBuilderDetector(ECbmModuleId::kPsd, ECbmDataType::kPsdDigi, "kPsd")}; + + Double_t fdEarliestTimeWinBeg = kdDefaultTimeWinBeg; + Double_t fdLatestTimeWinEnd = kdDefaultTimeWinEnd; + Double_t fdWidestTimeWinRange = kdDefaultTimeWinEnd - kdDefaultTimeWinBeg; + + Double_t fdTsStartTime = -1; + Double_t fdTsLength = -1; + Double_t fdTsOverLength = -1; + + /// Data input + /// FIXME: usage of CbmDigiManager in FairMq context?!? + /// => Maybe by registering vector (or vector reference) to ioman in Device? + //CbmDigiManager* fDigiMan = nullptr; //! + const std::vector<CbmTofDigi>* fT0DigiVec = nullptr; //! + TClonesArray* fTimeSliceMetaDataArray = nullptr; //! + const TimesliceMetaData* pTsMetaData = nullptr; + + const std::vector<CbmMuchDigi>* fMuchDigis = nullptr; + const std::vector<CbmMuchBeamTimeDigi>* fMuchBeamTimeDigis = nullptr; + const std::vector<CbmStsDigi>* fStsDigis = nullptr; + const std::vector<CbmTrdDigi>* fTrdDigis = nullptr; + const std::vector<CbmTofDigi>* fTofDigis = nullptr; + const std::vector<CbmRichDigi>* fRichDigis = nullptr; + const std::vector<CbmPsdDigi>* fPsdDigis = nullptr; + + bool DetIsPresent( ECbmModuleId detId ); + UInt_t GetNofDigis( ECbmModuleId detId ); + template <class Digi> const Digi* GetDigi( UInt_t uDigi ); + + /// Data ouptut + CbmEvent* fCurrentEvent = + nullptr; //! pointer to the event which is currently build + std::vector<CbmEvent*> fEventVector = {}; //! vector with all created events + + /// Monitoring histograms + /// => Pointers should be filled with TH1*, TH2*, TProfile*, ... + /// ==> To check if object N is of type T, use "T ObjectPointer = dynamic_cast<T>( fvpAllHistoPointers[N].first );" and check for nullptr + /// ==> To get back the original class name use "fvpAllHistoPointers[N].first->ClassName()" which returns a const char * (e.g. "TH1I") + /// ===> Usage example with feeding a THttpServer: + /// ===> #include "TH2.h" + /// ===> std::string sClassName = vHistos[ uHisto ].first.ClassName(); + /// ===> if( !strncmp( sClassName, "TH1", 3 ) ) + /// ===> server->Register( vHistos[ uHisto ].second.data(), dynamic_cast< TH1 * >(vHistos[ uHisto ].first) ); + /// ===> else if( !strncmp( sClassName, "TH2", 3 ) ) + /// ===> server->Register( vHistos[ uHisto ].second.data(), dynamic_cast< TH2 * >(vHistos[ uHisto ].first) ); + std::vector<std::pair<TNamed*, std::string>> + fvpAllHistoPointers; //! Vector of pointers to histograms + optional folder name + std::vector<std::pair<TCanvas*, std::string>> + fvpAllCanvasPointers; //! Vector of pointers to canvases + optional folder name + + TH1* fhEventTime = nullptr; //! histogram with the seed time of the events + TH1* fhEventDt = + nullptr; //! histogram with the interval in seed time of consecutive events + TH1* fhEventSize = + nullptr; //! histogram with the nb of all digis in the event + TH2* fhNbDigiPerEvtTime = + nullptr; //! histogram with the nb of all digis per event vs seed time of the events + std::vector<TH2*> fvhNbDigiPerEvtTimeDet = + {}; //! histograms with the nb of digis in each detector per event vs seed time of the events + + /// Internal state variables + UInt_t fuCurEv = 0; //! Event Counter + UInt_t fuErrors = 0; //! Error Counter + UInt_t fuNrTs = 0; //! Timeslice Counter + Double_t fdPrevEvtTime = 0.; //! Save previous time information + Double_t fdPrevEvtEndTime = + 0.; //! Save previous event last digi time information + + ClassDefNV(Cbm2021EventBuilderAlgo, 1); +}; + +#endif // CBM2021EVENTBUILDERALGO_H diff --git a/reco/eventbuilder/digis/Cbm2021EventBuilderTask.cxx b/reco/eventbuilder/digis/Cbm2021EventBuilderTask.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d338f840abdfdc3a0329bc9f26177338f845da0e --- /dev/null +++ b/reco/eventbuilder/digis/Cbm2021EventBuilderTask.cxx @@ -0,0 +1,342 @@ +/******************************************************************************** + * 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" +#include "Cbm2021EventBuilderTask.h" + +#include "CbmEvent.h" +#include "CbmDigiManager.h" + +#include "FairLogger.h" +#include "FairRootManager.h" +#include "FairRunOnline.h" + +#include "TClonesArray.h" +#include "TH1.h" +#include "TH2.h" +#include "THttpServer.h" +#include <TFile.h> + +// ---- Default constructor ------------------------------------------- +Cbm2021EventBuilderTask::Cbm2021EventBuilderTask() + : FairTask("Cbm2021EventBuilderTask") { + /// Create Algo. To be made generic/switchable when more event building algo are available! + fpAlgo = new Cbm2021EventBuilderAlgo(); +} + +// ---- Destructor ---------------------------------------------------- +Cbm2021EventBuilderTask::~Cbm2021EventBuilderTask() { +} + +// ---- Initialisation ---------------------------------------------- +void Cbm2021EventBuilderTask::SetParContainers() { + /// Nothing to do +} + +// ---- Init ---------------------------------------------------------- +InitStatus Cbm2021EventBuilderTask::Init() { + /// Get a handle from the IO manager + FairRootManager* ioman = FairRootManager::Instance(); + + // Get a pointer to the previous already existing data level + fDigiMan = CbmDigiManager::Instance(); + if (fbUseMuchBeamtimeDigi) { + fDigiMan->UseMuchBeamTimeDigi(); + } + fDigiMan->Init(); + + //Init STS digis + if (!fDigiMan->IsPresent(ECbmModuleId::kSts)) { + LOG(info) << "No STS digi input."; + }else{ + LOG(info) << "STS digi input."; + fStsDigis = new std::vector<CbmStsDigi>; + fpAlgo->SetStsDigis(fStsDigis); + } + + //Init MUCH digis + if (!fDigiMan->IsPresent(ECbmModuleId::kMuch)) { + LOG(info) << "No MUCH digi input."; + }else{ + LOG(info) << "MUCH digi input."; + if( fbUseMuchBeamtimeDigi ){ + fMuchBeamTimeDigis = new std::vector<CbmMuchBeamTimeDigi>; + fpAlgo->SetMuchBeamTimeDigis(fMuchBeamTimeDigis); + }else{ + fMuchDigis = new std::vector<CbmMuchDigi>; + fpAlgo->SetMuchDigis(fMuchDigis); + } + } + + //Init TRD digis + if (!fDigiMan->IsPresent(ECbmModuleId::kTrd)) { + LOG(info) << "No TRD digi input."; + }else{ + LOG(info) << "TRD digi input."; + fTrdDigis = new std::vector<CbmTrdDigi>; + fpAlgo->SetTrdDigis(fTrdDigis); + } + + //Init TOF digis + if (!fDigiMan->IsPresent(ECbmModuleId::kTof)) { + LOG(info) << "No TOF digi input."; + }else{ + LOG(info) << "TOF digi input."; + fTofDigis = new std::vector<CbmTofDigi>; + fpAlgo->SetTofDigis(fTofDigis); + } + + //Init RICH digis + if (!fDigiMan->IsPresent(ECbmModuleId::kRich)) { + LOG(info) << "No RICH digi input."; + }else{ + LOG(info) << "RICH digi input."; + fRichDigis = new std::vector<CbmRichDigi>; + fpAlgo->SetRichDigis(fRichDigis); + } + + //Init PSD digis + if (!fDigiMan->IsPresent(ECbmModuleId::kPsd)) { + LOG(info) << "No PSD digi input."; + }else{ + LOG(info) << "PSD digi input."; + fPsdDigis = new std::vector<CbmPsdDigi>; + fpAlgo->SetPsdDigis(fPsdDigis); + } + + /// Register output array (CbmEvent) + fEvents = new TClonesArray("CbmEvent", 100); + ioman->Register( + "CbmEvent", "Cbm_Event", fEvents, IsOutputBranchPersistent("CbmEvent")); + + if (!fEvents) LOG(fatal) << "Output branch was not created"; + + /// Call Algo Init method + if (kTRUE == fpAlgo->InitAlgo()) + return kSUCCESS; + else + return kFATAL; +} + +// ---- ReInit ------------------------------------------------------- +InitStatus Cbm2021EventBuilderTask::ReInit() { return kSUCCESS; } + +// ---- Exec ---------------------------------------------------------- +void Cbm2021EventBuilderTask::Exec(Option_t* /*option*/) { + LOG(debug2) + << "Cbm2021EventBuilderTask::Exec => Starting sequence"; + + //Read STS digis + if (fDigiMan->IsPresent(ECbmModuleId::kSts)) { + fStsDigis->clear(); + for( Int_t i=0; i<fDigiMan->GetNofDigis(ECbmModuleId::kSts); i++){ + const CbmStsDigi* Digi = fDigiMan->Get<CbmStsDigi>(i); + fStsDigis->insert( fStsDigis->begin()+i, *Digi ); + } + LOG(debug) << "Read: "<< fStsDigis->size() << " STS digis."; + LOG(debug) << "In DigiManager: "<< fDigiMan->GetNofDigis(ECbmModuleId::kSts) << " STS digis."; + } + + //Read MUCH digis + if (fDigiMan->IsPresent(ECbmModuleId::kMuch)) { + if( fbUseMuchBeamtimeDigi ){ + fMuchBeamTimeDigis->clear(); + for( Int_t i=0; i<fDigiMan->GetNofDigis(ECbmModuleId::kMuch); i++){ + const CbmMuchBeamTimeDigi* Digi = fDigiMan->Get<CbmMuchBeamTimeDigi>(i); + fMuchBeamTimeDigis->insert( fMuchBeamTimeDigis->begin()+i, *Digi ); + } + LOG(debug) << "Read: "<< fDigiMan->GetNofDigis(ECbmModuleId::kMuch) << " MUCH digis."; + LOG(debug) << "In DigiManager: "<< fMuchBeamTimeDigis->size() << " MUCH digis."; + }else{ + fMuchDigis->clear(); + for( Int_t i=0; i<fDigiMan->GetNofDigis(ECbmModuleId::kMuch); i++){ + const CbmMuchDigi* Digi = fDigiMan->Get<CbmMuchDigi>(i); + fMuchDigis->insert( fMuchDigis->begin()+i, *Digi ); + } + LOG(debug) << "Read: "<< fDigiMan->GetNofDigis(ECbmModuleId::kMuch) << " MUCH digis."; + LOG(debug) << "In DigiManager: "<< fMuchDigis->size() << " MUCH digis."; + } + } + + //Read TRD digis + if (fDigiMan->IsPresent(ECbmModuleId::kTrd)) { + fTrdDigis->clear(); + for( Int_t i=0; i<fDigiMan->GetNofDigis(ECbmModuleId::kTrd); i++){ + const CbmTrdDigi* Digi = fDigiMan->Get<CbmTrdDigi>(i); + fTrdDigis->insert( fTrdDigis->begin()+i, *Digi ); + } + LOG(debug) << "Read: "<< fDigiMan->GetNofDigis(ECbmModuleId::kTrd) << " TRD digis."; + LOG(debug) << "In DigiManager: "<< fTrdDigis->size() << " TRD digis."; + } + + //Read TOF digis + if (fDigiMan->IsPresent(ECbmModuleId::kTof)) { + fTofDigis->clear(); + for( Int_t i=0; i<fDigiMan->GetNofDigis(ECbmModuleId::kTof); i++){ + const CbmTofDigi* Digi = fDigiMan->Get<CbmTofDigi>(i); + fTofDigis->insert( fTofDigis->begin()+i, *Digi ); + } + LOG(debug) << "Read: "<< fDigiMan->GetNofDigis(ECbmModuleId::kTof) << " TOF digis."; + LOG(debug) << "In DigiManager: "<< fTofDigis->size() << " TOF digis."; + } + + //Read RICH digis + if (fDigiMan->IsPresent(ECbmModuleId::kRich)) { + fRichDigis->clear(); + for( Int_t i=0; i<fDigiMan->GetNofDigis(ECbmModuleId::kRich); i++){ + const CbmRichDigi* Digi = fDigiMan->Get<CbmRichDigi>(i); + fRichDigis->insert( fRichDigis->begin()+i, *Digi ); + } + LOG(debug) << "Read: "<< fDigiMan->GetNofDigis(ECbmModuleId::kRich) << " RICH digis."; + LOG(debug) << "In DigiManager: "<< fRichDigis->size() << " RICH digis."; + } + + //Read PSD digis + if (fDigiMan->IsPresent(ECbmModuleId::kPsd)) { + fPsdDigis->clear(); + for( Int_t i=0; i<fDigiMan->GetNofDigis(ECbmModuleId::kPsd); i++){ + const CbmPsdDigi* Digi = fDigiMan->Get<CbmPsdDigi>(i); + fPsdDigis->insert( fPsdDigis->begin()+i, *Digi ); + } + LOG(debug) << "Read: "<< fDigiMan->GetNofDigis(ECbmModuleId::kPsd) << " PSD digis."; + LOG(debug) << "In DigiManager: "<< fPsdDigis->size() << " PSD digis."; + } + + /// Call Algo ProcessTs method + fpAlgo->ProcessTs(); + + /// Save the resulting vector of events in TClonesArray + FillOutput(); + LOG(debug2) << "Cbm2021EventBuilderTask::Exec => Done"; +} + + +// ---- Finish -------------------------------------------------------- +void Cbm2021EventBuilderTask::Finish() { + if (fbFillHistos) { SaveHistos(); } // if( fbFillHistos ) + + /// Call Algo finish method + fpAlgo->Finish(); +} + +//---------------------------------------------------------------------- +void Cbm2021EventBuilderTask::FillOutput() { + /// Clear TClonesArray before usage. + fEvents->Delete(); + + /// Get vector reference from algo + std::vector<CbmEvent*> vEvents = fpAlgo->GetEventVector(); + + /// Move CbmEvent from temporary vector to TClonesArray + for (CbmEvent* event : vEvents) { + LOG(debug) << "Vector: " << event->ToString(); + new ((*fEvents)[fEvents->GetEntriesFast()]) CbmEvent(std::move(*event)); + LOG(debug) << "TClonesArray: " + << static_cast<CbmEvent*>( + fEvents->At(fEvents->GetEntriesFast() - 1)) + ->ToString(); + } // for( CbmEvent* event: vEvents ) + + /// Clear event vector after usage + fpAlgo->ClearEventVector(); +} +//---------------------------------------------------------------------- +void Cbm2021EventBuilderTask::SaveHistos() { + /// Obtain vector of pointers on each histo from the algo (+ optionally desired folder) + std::vector<std::pair<TNamed*, std::string>> vHistos = + fpAlgo->GetHistoVector(); + + /// (Re-)Create ROOT file to store the histos + TDirectory* oldDir = NULL; + TFile* histoFile = NULL; + /// Store current directory position to allow restore later + oldDir = gDirectory; + /// open separate histo file in recreate mode + histoFile = new TFile(fsOutFileName, "RECREATE"); + histoFile->cd(); + + /// Save all plots and create folders if needed + for (UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto) { + /// Make sure we end up in chosen folder + TString sFolder = vHistos[uHisto].second.data(); + if (nullptr == gDirectory->Get(sFolder)) gDirectory->mkdir(sFolder); + gDirectory->cd(sFolder); + + /// Write plot + vHistos[uHisto].first->Write(); + + histoFile->cd(); + } // for( UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto ) + + /// Restore original directory position + oldDir->cd(); + histoFile->Close(); +} +//---------------------------------------------------------------------- +void Cbm2021EventBuilderTask::SetFillHistos(Bool_t bFlag) { + fbFillHistos = bFlag; + if (nullptr != fpAlgo) fpAlgo->SetFillHistos(fbFillHistos); +} +void Cbm2021EventBuilderTask::SetOutFilename(TString sNameIn) { + fsOutFileName = sNameIn; +} + +void Cbm2021EventBuilderTask::SetReferenceDetector( + EventBuilderDetector refDet) { + if (nullptr != fpAlgo) fpAlgo->SetReferenceDetector(refDet); +} +void Cbm2021EventBuilderTask::AddDetector( + EventBuilderDetector selDet) { + if (nullptr != fpAlgo) fpAlgo->AddDetector(selDet); +} +void Cbm2021EventBuilderTask::RemoveDetector( + EventBuilderDetector selDet) { + if (nullptr != fpAlgo) fpAlgo->RemoveDetector(selDet); +} + +void Cbm2021EventBuilderTask::SetTriggerMinNumber( + ECbmModuleId selDet, + UInt_t uVal) { + if (nullptr != fpAlgo) fpAlgo->SetTriggerMinNumber(selDet, uVal); +} +void Cbm2021EventBuilderTask::SetTriggerMaxNumber( + ECbmModuleId selDet, + Int_t iVal) { + if (nullptr != fpAlgo) fpAlgo->SetTriggerMaxNumber(selDet, iVal); +} + +void Cbm2021EventBuilderTask::SetTriggerWindow(ECbmModuleId det, + Double_t dWinBeg, + Double_t dWinEnd) { + if (nullptr != fpAlgo) fpAlgo->SetTriggerWindow(det, dWinBeg, dWinEnd); +} + + +void Cbm2021EventBuilderTask::SetTsParameters( + Double_t dTsStartTime, + Double_t dTsLength, + Double_t dTsOverLength) { + if (nullptr != fpAlgo) + fpAlgo->SetTsParameters(dTsStartTime, dTsLength, dTsOverLength); +} + +void Cbm2021EventBuilderTask::SetEventOverlapMode( + EOverlapMode mode) { + if (nullptr != fpAlgo) fpAlgo->SetEventOverlapMode(mode); +} +void Cbm2021EventBuilderTask::SetIgnoreTsOverlap(Bool_t bFlagIn) { + if (nullptr != fpAlgo) fpAlgo->SetIgnoreTsOverlap(bFlagIn); +} +void Cbm2021EventBuilderTask::ChangeMuchBeamtimeDigiFlag( + Bool_t bFlagIn) { + if (nullptr != fpAlgo) fpAlgo->ChangeMuchBeamtimeDigiFlag(bFlagIn); + fbUseMuchBeamtimeDigi = bFlagIn; +} + +//---------------------------------------------------------------------- + +ClassImp(Cbm2021EventBuilderTask) diff --git a/reco/eventbuilder/digis/Cbm2021EventBuilderTask.h b/reco/eventbuilder/digis/Cbm2021EventBuilderTask.h new file mode 100644 index 0000000000000000000000000000000000000000..48c46db8685a3eb46170748c1bf027708c77ce8d --- /dev/null +++ b/reco/eventbuilder/digis/Cbm2021EventBuilderTask.h @@ -0,0 +1,118 @@ +/******************************************************************************** + * 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" * + ********************************************************************************/ +#ifndef CBMM2021EVENTBUILDERTASK_H +#define CBMM2021EVENTBUILDERTASK_H + +/// FAIRROOT headers +#include "FairTask.h" + +/// FAIRSOFT headers (geant, boost, ...) + +/// C/C++ headers +#include "CbmMuchBeamTimeDigi.h" +#include "CbmMuchDigi.h" +#include "CbmPsdDigi.h" +#include "CbmRichDigi.h" +#include "CbmStsDigi.h" +#include "CbmTofDigi.h" +#include "CbmTrdDigi.h" + +#include <array> +#include <map> +#include <set> +#include <tuple> +#include <vector> + +class CbmDigiManager; +class Cbm2021EventBuilderAlgo; +class EventBuilderDetector; +class TClonesArray; + +class Cbm2021EventBuilderTask : public FairTask { +public: + /** Default constructor **/ + Cbm2021EventBuilderTask(); + + Cbm2021EventBuilderTask( + const Cbm2021EventBuilderTask&) = delete; + Cbm2021EventBuilderTask + operator=(const Cbm2021EventBuilderTask&) = delete; + + /** Constructor with parameters (Optional) **/ + // Cbm2021EventBuilderTask(Int_t verbose); + + + /** Destructor **/ + ~Cbm2021EventBuilderTask(); + + + /** Initiliazation of task at the beginning of a run **/ + virtual InitStatus Init(); + + /** ReInitiliazation of task when the runID changes **/ + virtual InitStatus ReInit(); + + + /** Executed for each event. **/ + virtual void Exec(Option_t*); + + /** Load the parameter container from the runtime database **/ + virtual void SetParContainers(); + + /** Finish task called at the end of the run **/ + virtual void Finish(); + + void SetFillHistos(Bool_t bFlag = kTRUE); + void SetOutFilename(TString sNameIn); + + void SetReferenceDetector(EventBuilderDetector refDet); + void AddDetector(EventBuilderDetector selDet); + void RemoveDetector(EventBuilderDetector selDet); + + void SetTriggerMinNumber(ECbmModuleId selDet, UInt_t uVal); + void SetTriggerMaxNumber(ECbmModuleId selDet, Int_t iVal); + + void SetTriggerWindow(ECbmModuleId det, Double_t dWinBeg, Double_t dWinEnd); + + void SetTsParameters(Double_t dTsStartTime, + Double_t dTsLength, + Double_t dTsOverLength); + + void SetEventOverlapMode(EOverlapMode mode); + void SetIgnoreTsOverlap(Bool_t bFlagIn); + + void ChangeMuchBeamtimeDigiFlag(Bool_t bFlagIn = kFALSE); + +private: + void FillOutput(); + void SaveHistos(); + + CbmDigiManager* fDigiMan = nullptr; + std::vector<CbmMuchDigi>* fMuchDigis = nullptr; + std::vector<CbmMuchBeamTimeDigi>* fMuchBeamTimeDigis = nullptr; + std::vector<CbmStsDigi>* fStsDigis = nullptr; + std::vector<CbmTrdDigi>* fTrdDigis = nullptr; + std::vector<CbmTofDigi>* fTofDigis = nullptr; + std::vector<CbmRichDigi>* fRichDigis = nullptr; + std::vector<CbmPsdDigi>* fPsdDigis = nullptr; + + Bool_t fbUseMuchBeamtimeDigi = kTRUE; //! Switch between MUCH digi classes + + Cbm2021EventBuilderAlgo* fpAlgo = nullptr; + + TClonesArray* fEvents = nullptr; //! output container of CbmEvents + + Bool_t fbFillHistos {kTRUE}; //! Switch ON/OFF filling of histograms + + /** Name of the histogram output file **/ + TString fsOutFileName {"data/HistosEvtWin.root"}; + + ClassDef(Cbm2021EventBuilderTask, 1); +}; + +#endif // CBMM2021EVENTBUILDERTASK_H