Skip to content
Snippets Groups Projects
CbmMcbm2019TimeWinEventBuilderAlgo.cxx 42 KiB
Newer Older
/********************************************************************************
 *    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 "CbmMcbm2019TimeWinEventBuilderAlgo.h"

/// CBM headers
#include "CbmEvent.h"
#include "CbmMuchBeamTimeDigi.h"
#include "CbmPsdDigi.h"
Administrator's avatar
Administrator committed
#include "CbmRichDigi.h"
#include "CbmStsDigi.h"
#include "CbmTofDigi.h"
#include "CbmTrdDigi.h"
#include "TimesliceMetaData.h"

#include "CbmDigiManager.h"

/// FAIRROOT headers
#include "FairLogger.h"
#include "FairRootManager.h"
#include "FairRunOnline.h"

/// FAIRSOFT headers (geant, boost, ...)
Administrator's avatar
Administrator committed
#include "TCanvas.h"
#include "TClonesArray.h"
#include "TH1.h"
Administrator's avatar
Administrator committed
#include "TH2.h"
#include "THttpServer.h"

/// C/C++ headers

// ---- Default constructor --------------------------------------------
CbmMcbm2019TimeWinEventBuilderAlgo::CbmMcbm2019TimeWinEventBuilderAlgo() {}

// ---- Destructor -----------------------------------------------------
CbmMcbm2019TimeWinEventBuilderAlgo::~CbmMcbm2019TimeWinEventBuilderAlgo() {}

// ---- Init -----------------------------------------------------------
Bool_t CbmMcbm2019TimeWinEventBuilderAlgo::InitAlgo() {
Administrator's avatar
Administrator committed
  LOG(info)
    << "CbmMcbm2019TimeWinEventBuilderAlgo::InitAlgo => Starting sequence";

  // Get a handle from the IO manager
  FairRootManager* ioman = FairRootManager::Instance();

  // Get a pointer to the previous already existing data level
  fDigiMan = CbmDigiManager::Instance();
  fDigiMan->UseMuchBeamTimeDigi();
  fDigiMan->Init();

  /// 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 ) )
Administrator's avatar
Administrator committed

  /// 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)
Administrator's avatar
Administrator committed

  /// Access the TS metadata to know TS start tim
  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)
Administrator's avatar
Administrator committed

  if (fbFillHistos) { CreateHistograms(); }  // if( fbFillHistos )
Administrator's avatar
Administrator committed
  LOG(info) << "CbmMcbm2019TimeWinEventBuilderAlgo::InitAlgo => Done";
Administrator's avatar
Administrator committed
  return kTRUE;
}

// ---- ProcessTs ------------------------------------------------------
void CbmMcbm2019TimeWinEventBuilderAlgo::ProcessTs() {
Administrator's avatar
Administrator committed
  LOG_IF(info, fuNrTs % 1000 == 0) << "Begin of TS " << fuNrTs;
Administrator's avatar
Administrator committed
  InitTs();
Administrator's avatar
Administrator committed
  BuildEvents();
Administrator's avatar
Administrator committed
  /// 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++;
Administrator's avatar
Administrator committed
    /// Prevent building over TS edge
    fCurrentEvent = nullptr;
  }  // if( nullptr != fCurrentEvent )
Administrator's avatar
Administrator committed
  LOG(debug) << "Found " << fEventVector.size() << " triggered events";
Administrator's avatar
Administrator committed
  if (fbFillHistos) { FillHistos(); }  // if( fbFillHistos )
Administrator's avatar
Administrator committed
  fuNrTs++;
void CbmMcbm2019TimeWinEventBuilderAlgo::ClearEventVector() {
Administrator's avatar
Administrator committed
  /// 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 CbmMcbm2019TimeWinEventBuilderAlgo::Finish() {
Administrator's avatar
Administrator committed
  LOG(info) << "Total errors: " << fuErrors;
}

// ---------------------------------------------------------------------
Bool_t CbmMcbm2019TimeWinEventBuilderAlgo::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;
    }  // if( ! fT0DigiVec )
  }    // if( ECbmModuleId::kT0 == det.detId )
  else {
    if (!fDigiMan->IsPresent(det.detId)) {
      LOG(info) << "No " << det.sName << " digi input found.";
      return kFALSE;
    }  // if( ! fDigiMan->IsPresent(ECbmModuleId::kSts) )
  }    // else of if( ECbmModuleId::kT0 == det.detId )

  return kTRUE;
}
// ---------------------------------------------------------------------
void CbmMcbm2019TimeWinEventBuilderAlgo::InitTs() {
Administrator's avatar
Administrator committed
  /// Reset TS based variables (analysis per TS = no building over the border)
  fRefDet.fuStartIndex = 0;
  fRefDet.fuEndIndex   = 0;
  /// Loop on detectors in selection list
  for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin();
       det != fvDets.end();
       ++det) {
  }  // for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det)
void CbmMcbm2019TimeWinEventBuilderAlgo::BuildEvents() {
  /// Call LoopOnSeed with proper template argument
Administrator's avatar
Administrator committed
    case ECbmModuleId::kSts: {
      LoopOnSeeds<CbmStsDigi>();
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kSts:
    case ECbmModuleId::kMuch: {
      LoopOnSeeds<CbmMuchBeamTimeDigi>();
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kMuch:
    case ECbmModuleId::kTrd: {
      LoopOnSeeds<CbmTrdDigi>();
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kTrd:
    case ECbmModuleId::kTof: {
      LoopOnSeeds<CbmTofDigi>();
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kTof:
    case ECbmModuleId::kRich: {
      LoopOnSeeds<CbmRichDigi>();
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kRich:
    case ECbmModuleId::kPsd: {
      LoopOnSeeds<CbmPsdDigi>();
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kPsd:
    case ECbmModuleId::kT0: {
      LoopOnSeeds<CbmTofDigi>();
      break;
    }  // case ECbmModuleId::kT0:
    default: {
      LOG(fatal) << "CbmMcbm2019TimeWinEventBuilderAlgo::BuildEvents => "
                 << "Trying to search event seeds with unsupported det: "
Administrator's avatar
Administrator committed
    }  // default:
  }    // switch( *det )
Administrator's avatar
Administrator committed
template<class DigiSeed>
void CbmMcbm2019TimeWinEventBuilderAlgo::LoopOnSeeds() {
  pTsMetaData =
    dynamic_cast<TimesliceMetaData*>(fTimeSliceMetaDataArray->At(0));
Administrator's avatar
Administrator committed
  if (nullptr == pTsMetaData)
    LOG(fatal) << Form("CbmMcbm2019TimeWinEventBuilderAlgo::LoopOnSeeds => "
                       "No TS metadata found for TS %6u.",
Administrator's avatar
Administrator committed
                       fuNrTs);

  /// Print warning in first TS if time window borders out of potential overlap
Administrator's avatar
Administrator committed
  if ((0.0 < fdEarliestTimeWinBeg
       && pTsMetaData->GetOverlapDuration() < fdLatestTimeWinEnd)
      || (pTsMetaData->GetOverlapDuration() < fdWidestTimeWinRange)) {
    LOG(warning) << "CbmMcbm2019TimeWinEventBuilderAlgo::LoopOnSeeds => "
                 << Form("Event window not fitting in TS overlap, risk of "
                         "incomplete events: %f %f %f %llu",
                         fdEarliestTimeWinBeg,
                         fdLatestTimeWinEnd,
                         fdWidestTimeWinRange,
                         pTsMetaData->GetOverlapDuration());
  }  // 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 =
    pTsMetaData->GetStartTime()
    + (0.0 < fdEarliestTimeWinBeg ? 0.0 : -fdEarliestTimeWinBeg);
  Double_t dSeedWindowEnd =
    pTsMetaData->GetOverlapStartTime()
    + (0.0 < fdEarliestTimeWinBeg ? 0.0 : -fdEarliestTimeWinBeg);
Administrator's avatar
Administrator committed
  if (fbIgnoreTsOverlap) {
    dSeedWindowBeg = pTsMetaData->GetStartTime();
    dSeedWindowEnd = pTsMetaData->GetOverlapStartTime();
  }  // if( fbIgnoreTsOverlap )

  if (ECbmModuleId::kT0 == fRefDet.detId) {
    if (fT0DigiVec) {
      /// Loop on size of vector
      UInt_t uNbRefDigis = fT0DigiVec->size();
      /// Loop on size of vector
Administrator's avatar
Administrator committed
      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) << "CbmMcbm2019TimeWinEventBuilderAlgo::LoopOnSeeds => "
                 << "T0 as reference detector but vector not found!";
  }  // if (ECbmModuleId::kT0 == fRefDet.detId)
  else {
    UInt_t uNbRefDigis = (0 < fDigiMan->GetNofDigis(fRefDet.detId)
                            ? fDigiMan->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 = fDigiMan->Get<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
Administrator's avatar
Administrator committed
void CbmMcbm2019TimeWinEventBuilderAlgo::CheckSeed(Double_t dSeedTime,
  /// If previous event valid and event overlap not allowed, check if we are in overlap
  /// and react accordingly
Administrator's avatar
Administrator committed
  if (nullptr != fCurrentEvent && EOverlapMode::AllowOverlap != fOverMode
      && dSeedTime - fdPrevEvtTime < fdWidestTimeWinRange) {
    /// Within overlap range
Administrator's avatar
Administrator committed
    switch (fOverMode) {
      case EOverlapMode::NoOverlap: {
        /// No overlap allowed => reject
Administrator's avatar
Administrator committed
        LOG(debug1) << "Reject seed due to overlap";
Administrator's avatar
Administrator committed
      }  // case EOverlapMode::NoOverlap:
      case EOverlapMode::MergeOverlap: {
        /// Merge overlap mode => do nothing and go on filling current event
        break;
Administrator's avatar
Administrator committed
      }  // case EOverlapMode::MergeOverlap:
      case EOverlapMode::AllowOverlap: {
        /// Not in Merge overlap mode => should have been catched before, nothing to do
        break;
Administrator's avatar
Administrator committed
      }  // case EOverlapMode::AllowOverlap:
    }    // switch( fOverMode )
  }      // if( prev Event exists and overlap not allowed and 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 overlap not allowed and 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) {
Administrator's avatar
Administrator committed
      case ECbmModuleId::kSts: {
        SearchMatches<CbmStsDigi>(dSeedTime, fRefDet);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kSts:
      case ECbmModuleId::kMuch: {
        SearchMatches<CbmMuchBeamTimeDigi>(dSeedTime, fRefDet);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kMuch:
      case ECbmModuleId::kTrd: {
        SearchMatches<CbmTrdDigi>(dSeedTime, fRefDet);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kTrd:
      case ECbmModuleId::kTof: {
        SearchMatches<CbmTofDigi>(dSeedTime, fRefDet);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kTof:
      case ECbmModuleId::kRich: {
        SearchMatches<CbmRichDigi>(dSeedTime, fRefDet);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kRich:
      case ECbmModuleId::kPsd: {
        SearchMatches<CbmPsdDigi>(dSeedTime, fRefDet);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kPsd:
      case ECbmModuleId::kT0: {
        SearchMatches<CbmTofDigi>(dSeedTime, fRefDet);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kT0:
      default: {
        LOG(fatal) << "CbmMcbm2019TimeWinEventBuilderAlgo::LoopOnSeeds => "
                   << "Trying to search matches with unsupported det: "
                   << "You may want to add support for it in the method.";
Administrator's avatar
Administrator committed
      }  // default:
    }    // switch( fRefDet )

    /// Also add the seed if the window starts after the seed
    if (0 < fRefDet.fdTimeWinBeg) AddDigiToEvent(fRefDet, uSeedDigiIdx);
Administrator's avatar
Administrator committed
  }  // 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) {
Administrator's avatar
Administrator committed
      case ECbmModuleId::kSts: {
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kSts:
      case ECbmModuleId::kMuch: {
        SearchMatches<CbmMuchBeamTimeDigi>(dSeedTime, *det);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kMuch:
      case ECbmModuleId::kTrd: {
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kTrd:
      case ECbmModuleId::kTof: {
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kTof:
      case ECbmModuleId::kRich: {
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kRich:
      case ECbmModuleId::kPsd: {
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kPsd:
      case ECbmModuleId::kT0: {
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kT0:
      default: {
        LOG(fatal) << "CbmMcbm2019TimeWinEventBuilderAlgo::LoopOnSeeds => "
                   << "Trying to search matches with unsupported det: "
                   << (*det).sName << std::endl
                   << "You may want to add support for it in the method.";
Administrator's avatar
Administrator committed
      }  // 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
Administrator's avatar
Administrator committed
  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
Administrator's avatar
Administrator committed
    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 ) )
Administrator's avatar
Administrator committed
  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 ) )
Administrator's avatar
Administrator committed
template<class DigiCheck>
void CbmMcbm2019TimeWinEventBuilderAlgo::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) {
      /// 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();
        /// 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) << "CbmMcbm2019TimeWinEventBuilderAlgo::SearchMatches => "
                 << "T0 as selection detector but vector not found!";
  }  // if( ECbmModuleId::kT0 == detMatch.detId )
  else {
    UInt_t uNbSelDigis = (0 < fDigiMan->GetNofDigis(detMatch.detId)
                            ? fDigiMan->GetNofDigis(detMatch.detId)
                            : 0);
    /// Loop on size of vector
    for (UInt_t uDigi = detMatch.fuStartIndex; uDigi < uNbSelDigis; ++uDigi) {
      const DigiCheck* pDigi = fDigiMan->Get<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 CbmMcbm2019TimeWinEventBuilderAlgo::AddDigiToEvent(
  EventBuilderDetector& det,
  Int_t _entry) {
  fCurrentEvent->AddData(det.dataType, _entry);
Bool_t CbmMcbm2019TimeWinEventBuilderAlgo::HasTrigger(CbmEvent* event) {
  if (kFALSE == CheckTriggerConditions(event, fRefDet)) {
Administrator's avatar
Administrator committed
    return kFALSE;
  }  // if (kFALSE == CheckTriggerConditions(event, fRefDet) )
  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 )
Bool_t CbmMcbm2019TimeWinEventBuilderAlgo::CheckTriggerConditions(
  CbmEvent* event,
  EventBuilderDetector& det) {
  /// Check if both Trigger conditions disabled for this detector
  if (0 == det.fuTriggerMinDigis && det.fiTriggerMaxDigis < 0) {
  }  // if( 0 == det.fuTriggerMinDigis && det.fiTriggerMaxDigis < 0 )

  /// Check if detector present
    /// FIXME: special case to be removed once T0 supported by DigiManager
Administrator's avatar
Administrator committed
    if (!(fT0DigiVec)) {
      LOG(warning) << "Event does not have digis storage for T0"
                   << " while the following trigger minimum are defined: "
                   << det.fuTriggerMinDigis << " " << det.fiTriggerMaxDigis;
Administrator's avatar
Administrator committed
      return kFALSE;
    }  // if( !(fT0DigiVec) )
  }    // if( ECbmDataType::kT0Digi == det.detId )
Administrator's avatar
Administrator committed
  else {
    if (!fDigiMan->IsPresent(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;
Administrator's avatar
Administrator committed
    }  // if( !fDigiMan->IsPresent( det ) )
  }    // else of if( ECbmDataType::kT0Digi == det )

  /// Check Minimal trigger acceptance by minimal number
  Int_t iNbDigis = event->GetNofData(det.dataType);
  if ((-1 != iNbDigis)
      && (det.fuTriggerMinDigis <= static_cast<UInt_t>(iNbDigis))) {
  }  // if( ( -1 != iNbDigis ) && ( det.fuTriggerMinDigis <= static_cast< UInt_t >( iNbDigis )  )
Administrator's avatar
Administrator committed
  else {
    LOG(debug2) << "Event does not have enough digis: " << iNbDigis << " vs "
                << det.fuTriggerMinDigis << " for " << det.sName;
Administrator's avatar
Administrator committed
    return kFALSE;
  }  // else of if( ( -1 != iNbDigis ) && ( det.fuTriggerMinDigis <= static_cast< UInt_t >( iNbDigis )  )

  /// Check trigger rejection by maximal number
Administrator's avatar
Administrator committed
  else {
    LOG(debug2) << "Event Has too many digis: " << iNbDigis << " vs "
                << det.fiTriggerMaxDigis << " for " << det.sName;
Administrator's avatar
Administrator committed
    return kFALSE;
  }  // else of if( iNbDigis < det.fiTriggerMaxDigis )
}
//----------------------------------------------------------------------
void CbmMcbm2019TimeWinEventBuilderAlgo::CreateHistograms() {
  /// FIXME: Disable clang formatting for histograms declaration for now
  /* clang-format off */
Administrator's avatar
Administrator committed
  fhEventTime = new TH1F("hEventTime",
                         "seed time of the events; Seed time [s]; Events",
  fhEventDt   = new TH1F( "fhEventDt",
                          "interval in seed time of consecutive events; Seed time [s]; Events",
                          2100, -100.5, 1999.5);
Administrator's avatar
Administrator committed
  fhEventSize =
    new TH1F("hEventSize",
             "nb of all  digis in the event; Nb Digis []; Events []",
Administrator's avatar
Administrator committed
  fhNbDigiPerEvtTime =
    new TH2I("hNbDigiPerEvtTime",
             "nb of all  digis per event vs seed time of the events; Seed time "
             "[s]; Nb Digis []; Events []",
Administrator's avatar
Administrator committed

  /// 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");
  }  // for( std::vector<TH2*>::iterator itHist = fvhNbDigiPerEvtTimeDet.begin(); itHist != fvhNbDigiPerEvtTimeDet.end(); ++itHist )

  /// FIXME: Re-enable clang formatting after histograms declaration
  /* clang-format on */
void CbmMcbm2019TimeWinEventBuilderAlgo::FillHistos() {
  Double_t dPreEvtTime = -1.0;
Administrator's avatar
Administrator committed
  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();
Administrator's avatar
Administrator committed
  }  // for( CbmEvent * evt: fEventVector )
void CbmMcbm2019TimeWinEventBuilderAlgo::ResetHistograms(
  Bool_t /*bResetTime*/) {
Administrator's avatar
Administrator committed
  fhEventTime->Reset();
  fhEventDt->Reset();
  fhEventSize->Reset();
Administrator's avatar
Administrator committed
  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 )
Administrator's avatar
Administrator committed

  /*
   if( kTRUE == bResetTime )
   {
      /// Also reset the Start time for the evolution plots!
      fdStartTime = -1.0;
   } // if( kTRUE == bResetTime )
*/
}
//----------------------------------------------------------------------
void CbmMcbm2019TimeWinEventBuilderAlgo::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 CbmMcbm2019TimeWinEventBuilderAlgo::AddDetector(ECbmModuleId selDet,
                                                     ECbmDataType dataTypeIn,
                                                     std::string sNameIn,
                                                     UInt_t uTriggerMinDigisIn,
                                                     Int_t iTriggerMaxDigisIn,
                                                     Double_t fdTimeWinBegIn,
                                                     Double_t fdTimeWinEndIn) {
Administrator's avatar
Administrator committed

  /// FIXME: Deprecated method to be removed later. For now create temp object.
  AddDetector(EventBuilderDetector(selDet,
                                   dataTypeIn,
                                   sNameIn,
                                   uTriggerMinDigisIn,
                                   iTriggerMaxDigisIn,
                                   fdTimeWinBegIn,
                                   fdTimeWinEndIn));
}
//----------------------------------------------------------------------
void CbmMcbm2019TimeWinEventBuilderAlgo::SetReferenceDetector(
  ECbmModuleId refDet) {
Administrator's avatar
Administrator committed
    case ECbmModuleId::kSts: {
      SetReferenceDetector(kEventBuilderDetSts);
Administrator's avatar
Administrator committed
    case ECbmModuleId::kMuch: {
      SetReferenceDetector(kEventBuilderDetMuch);
Administrator's avatar
Administrator committed
    case ECbmModuleId::kTrd: {
      SetReferenceDetector(kEventBuilderDetTrd);
Administrator's avatar
Administrator committed
    case ECbmModuleId::kTof: {
      SetReferenceDetector(kEventBuilderDetTof);
    }  // case ECbmModuleId::kTof:
    case ECbmModuleId::kRich: {
      SetReferenceDetector(kEventBuilderDetRich);
Administrator's avatar
Administrator committed
    case ECbmModuleId::kPsd: {
      SetReferenceDetector(kEventBuilderDetPsd);
Administrator's avatar
Administrator committed
    case ECbmModuleId::kT0: {
      SetReferenceDetector(kEventBuilderDetT0);
Administrator's avatar
Administrator committed
    default: {
      LOG(fatal)
        << "CbmMcbm2019TimeWinEventBuilderAlgo::SetReferenceDetector => "
        << "Trying to change reference to unsupported det: " << refDet
        << std::endl
        << "This method is deprecated and will be removed soon, "
        << "please use the full version of it.";
  LOG(warning)
    << "CbmMcbm2019TimeWinEventBuilderAlgo::SetReferenceDetector => "
    << "Changing reference detector with deprecated method to: "
    << fRefDet.sName << std::endl
    << "This method is deprecated, does not set all parameters "
    << "and will be removed soon, please use the full version of it.";
void CbmMcbm2019TimeWinEventBuilderAlgo::AddDetector(ECbmModuleId selDet) {
Administrator's avatar
Administrator committed
  switch (selDet) {
    case ECbmModuleId::kSts: {
      AddDetector(kEventBuilderDetSts);
Administrator's avatar
Administrator committed
    case ECbmModuleId::kMuch: {
      AddDetector(kEventBuilderDetMuch);
Administrator's avatar
Administrator committed
    case ECbmModuleId::kTrd: {
      AddDetector(kEventBuilderDetTrd);
Administrator's avatar
Administrator committed
    case ECbmModuleId::kTof: {
      AddDetector(kEventBuilderDetTof);
    }  // case ECbmModuleId::kTof:
    case ECbmModuleId::kRich: {
      AddDetector(kEventBuilderDetRich);
Administrator's avatar
Administrator committed
    case ECbmModuleId::kPsd: {
      AddDetector(kEventBuilderDetPsd);
Administrator's avatar
Administrator committed
    case ECbmModuleId::kT0: {
      AddDetector(kEventBuilderDetT0);
Administrator's avatar
Administrator committed
    default: {
      LOG(fatal) << "CbmMcbm2019TimeWinEventBuilderAlgo::AddDetector => "
                 << "Trying to change reference to unsupported det: " << selDet
                 << std::endl
                 << "This method is deprecated and will be removed soon, "
                 << "please use the full version of it.";
  LOG(warning)
    << "CbmMcbm2019TimeWinEventBuilderAlgo::AddDetector => "
    << "Changing reference detector with deprecated method for: " << selDet
    << std::endl
    << "This method is deprecated, does not set all parameters "
    << "and will be removed soon, please use the full version of it.";
void CbmMcbm2019TimeWinEventBuilderAlgo::RemoveDetector(ECbmModuleId selDet) {
  for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin();
       det != fvDets.end();
       ++det) {
    if ((*det).detId == selDet) {
      fvDets.erase(det);
      return;
    }  // if( (*det).detId  == selDet )
  }  // for( std::vector< EventBuilderDetector >::iterator det = fvDets.begin(); det != fvDets.end(); ++det )
  LOG(warning) << "CbmMcbm2019TimeWinEventBuilderAlgo::RemoveDetector => Doing "
                  "nothing, selection detector not in list!"
               << selDet;
}
//----------------------------------------------------------------------
void CbmMcbm2019TimeWinEventBuilderAlgo::SetReferenceDetector(
  EventBuilderDetector refDetIn) {
  /// Loop on selection detectors
  for (std::vector<EventBuilderDetector>::iterator det = fvDets.begin();
       det != fvDets.end();
       ++det) {
    if ((*det) == refDetIn) {
      LOG(warning)
        << "CbmMcbm2019TimeWinEventBuilderAlgo::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)
      << "CbmMcbm2019TimeWinEventBuilderAlgo::SetReferenceDetector => "
         "Doing nothing, identical reference detector already in use";
  }  // if( fRefDet == refDetIn )
  else {
    LOG(info) << "CbmMcbm2019TimeWinEventBuilderAlgo::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 CbmMcbm2019TimeWinEventBuilderAlgo::AddDetector(
  EventBuilderDetector selDet) {
  if (fRefDet == selDet) {
    LOG(fatal) << "CbmMcbm2019TimeWinEventBuilderAlgo::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) << "CbmMcbm2019TimeWinEventBuilderAlgo::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 CbmMcbm2019TimeWinEventBuilderAlgo::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) << "CbmMcbm2019TimeWinEventBuilderAlgo::RemoveDetector => Doing "
                  "nothing, selection detector not in list!"
               << selDet.sName;
}
//----------------------------------------------------------------------
void CbmMcbm2019TimeWinEventBuilderAlgo::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)
    << "CbmMcbm2019TimeWinEventBuilderAlgo::SetTriggerMinNumber => "
       "Doing nothing, detector neither reference nor in selection list!"
    << selDet;
void CbmMcbm2019TimeWinEventBuilderAlgo::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 )