Skip to content
Snippets Groups Projects
CbmMcbm2019TimeWinEventBuilderAlgo.cxx 45.7 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 --------------------------------------------
Administrator's avatar
Administrator committed
CbmMcbm2019TimeWinEventBuilderAlgo::CbmMcbm2019TimeWinEventBuilderAlgo() {}

// ---- Destructor -----------------------------------------------------
Administrator's avatar
Administrator committed
CbmMcbm2019TimeWinEventBuilderAlgo::~CbmMcbm2019TimeWinEventBuilderAlgo() {}

// ---- Init -----------------------------------------------------------
Administrator's avatar
Administrator committed
Bool_t CbmMcbm2019TimeWinEventBuilderAlgo::InitAlgo() {
  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();

  // T0 is not included in DigiManager
  fT0DigiVec = ioman->InitObjectAs<std::vector<CbmTofDigi> const*>("T0Digi");
  if (!fT0DigiVec) {
    LOG(info) << "No T0 digi input.";
    if (ECbmModuleId::kT0 == fRefDet) {
      LOG(fatal) << "No digi input for reference detector, stopping there!";
    }  // if( ECbmModuleId::kT0 == fRefDet )
  }    // if( ! fT0DigiVec )

  if (!fDigiMan->IsPresent(ECbmModuleId::kSts)) {
    LOG(info) << "No STS digi input.";
    if (ECbmModuleId::kSts == fRefDet) {
      LOG(fatal) << "No digi input for reference detector, stopping there!";
    }  // if( ECbmModuleId::kT0 == fRefDet )
  }    // if( ! fDigiMan->IsPresent(ECbmModuleId::kSts) )

  if (!fDigiMan->IsPresent(ECbmModuleId::kMuch)) {
    LOG(info) << "No MUCH digi input.";
    if (ECbmModuleId::kMuch == fRefDet) {
      LOG(fatal) << "No digi input for reference detector, stopping there!";
    }  // if( ECbmModuleId::kT0 == fRefDet )
  }    // if( ! fDigiMan->IsPresent(ECbmModuleId::kMuch) )

  if (!fDigiMan->IsPresent(ECbmModuleId::kTrd)) {
    LOG(info) << "No TRD digi input.";
    if (ECbmModuleId::kTrd == fRefDet) {
      LOG(fatal) << "No digi input for reference detector, stopping there!";
    }  // if( ECbmModuleId::kT0 == fRefDet )
  }    // if( ! fDigiMan->IsPresent(ECbmModuleId::kTrd) )

  if (!fDigiMan->IsPresent(ECbmModuleId::kTof)) {
    LOG(info) << "No TOF digi input.";
    if (ECbmModuleId::kTof == fRefDet) {
      LOG(fatal) << "No digi input for reference detector, stopping there!";
    }  // if( ECbmModuleId::kT0 == fRefDet )
  }    // if( ! fDigiMan->IsPresent(ECbmModuleId::kTof) )

  if (!fDigiMan->IsPresent(ECbmModuleId::kRich)) {
    LOG(info) << "No RICH digi input.";
    if (ECbmModuleId::kRich == fRefDet) {
      LOG(fatal) << "No digi input for reference detector, stopping there!";
    }  // if( ECbmModuleId::kT0 == fRefDet )
  }    // if( ! fDigiMan->IsPresent(ECbmModuleId::kRich) )

  if (!fDigiMan->IsPresent(ECbmModuleId::kPsd)) {
    LOG(info) << "No PSD digi input.";
    if (ECbmModuleId::kPsd == fRefDet) {
      LOG(fatal) << "No digi input for reference detector, stopping there!";
    }  // if( ECbmModuleId::kT0 == fRefDet )
  }    // if( ! fDigiMan->IsPresent(ECbmModuleId::kPsd) )

  /// 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

  /// Store the time window for the reference detector
  switch (fRefDet) {
    case ECbmModuleId::kSts: {
      fdRefTimeWinBeg = fdStsTimeWinBeg;
      fdRefTimeWinEnd = fdStsTimeWinEnd;
      break;
    }  // case ECbmModuleId::kSts:
    case ECbmModuleId::kMuch: {
      fdRefTimeWinBeg = fdMuchTimeWinBeg;
      fdRefTimeWinEnd = fdMuchTimeWinEnd;
      break;
    }  // case ECbmModuleId::kMuch:
    case ECbmModuleId::kTrd: {
      fdRefTimeWinBeg = fdTrdTimeWinBeg;
      fdRefTimeWinEnd = fdTrdTimeWinEnd;
      break;
    }  // case ECbmModuleId::kTrd:
    case ECbmModuleId::kTof: {
      fdRefTimeWinBeg = fdTofTimeWinBeg;
      fdRefTimeWinEnd = fdTofTimeWinEnd;
      break;
    }  // case ECbmModuleId::kTof:
    case ECbmModuleId::kRich: {
      fdRefTimeWinBeg = fdRichTimeWinBeg;
      fdRefTimeWinEnd = fdRichTimeWinEnd;
      break;
    }  // case ECbmModuleId::kRich:
    case ECbmModuleId::kPsd: {
      fdRefTimeWinBeg = fdPsdTimeWinBeg;
      fdRefTimeWinEnd = fdPsdTimeWinEnd;
      break;
    }  // case ECbmModuleId::kPsd:
    case ECbmModuleId::kT0: {
      fdRefTimeWinBeg = fdT0TimeWinBeg;
      fdRefTimeWinEnd = fdT0TimeWinEnd;
      break;
    }  // case ECbmModuleId::kT0:
    default: {
      LOG(fatal) << "CbmMcbm2019TimeWinEventBuilderAlgo::Init => "
                 << "Trying to use unsupported detectore as reference: "
                 << fRefDet;
      break;
    }  // default:
  }    // switch( fRefDet )
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 ------------------------------------------------------
Administrator's avatar
Administrator committed
void CbmMcbm2019TimeWinEventBuilderAlgo::ProcessTs() {
  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++;
Administrator's avatar
Administrator committed
void CbmMcbm2019TimeWinEventBuilderAlgo::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 ---------------------------------------------------------
Administrator's avatar
Administrator committed
void CbmMcbm2019TimeWinEventBuilderAlgo::Finish() {
  LOG(info) << "Total errors: " << fuErrors;
}

// ---------------------------------------------------------------------
Administrator's avatar
Administrator committed
void CbmMcbm2019TimeWinEventBuilderAlgo::InitTs() {
  /// Reset TS based variables (analysis per TS = no building over the border)
  fuStartIndexT0   = 0;
  fuStartIndexSts  = 0;
  fuStartIndexMuch = 0;
  fuStartIndexTrd  = 0;
  fuStartIndexTof  = 0;
  fuStartIndexRich = 0;
  fuStartIndexPsd  = 0;
  fuEndIndexT0     = 0;
  fuEndIndexSts    = 0;
  fuEndIndexMuch   = 0;
  fuEndIndexTrd    = 0;
  fuEndIndexTof    = 0;
  fuEndIndexRich   = 0;
  fuEndIndexPsd    = 0;
Administrator's avatar
Administrator committed
void CbmMcbm2019TimeWinEventBuilderAlgo::BuildEvents() {
  /// Call LoopOnSeed with proper template argument
Administrator's avatar
Administrator committed
  switch (fRefDet) {
    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: "
                 << fRefDet;
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));
  if (nullptr == pTsMetaData)
    LOG(fatal) << Form("CbmMcbm2019TimeWinEventBuilderAlgo::LoopOnSeeds => No "
                       "TS metadata found for TS %6u.",
                       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);
  if (fbIgnoreTsOverlap) {
    dSeedWindowBeg = pTsMetaData->GetStartTime();
    dSeedWindowEnd = pTsMetaData->GetOverlapStartTime();
  }  // if( fbIgnoreTsOverlap )

  switch (fRefDet) {
    case ECbmModuleId::kSts:
    case ECbmModuleId::kMuch:
    case ECbmModuleId::kTrd:
    case ECbmModuleId::kTof:
    case ECbmModuleId::kRich:
Administrator's avatar
Administrator committed
    case ECbmModuleId::kPsd: {
      UInt_t uNbRefDigis =
        (0 < fDigiMan->GetNofDigis(fRefDet) ? fDigiMan->GetNofDigis(fRefDet)
                                            : 0);
      /// 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);
        const DigiSeed* pDigi = fDigiMan->Get<DigiSeed>(uDigi);
        /// Check that _entry is not out of range
Administrator's avatar
Administrator committed
        if (nullptr != pDigi) {
          Double_t dTime = pDigi->GetTime();

          /// Check if seed in acceptance window
Administrator's avatar
Administrator committed
          if (dTime < dSeedWindowBeg) {
Administrator's avatar
Administrator committed
          }  // if( dTime < dSeedWindowBeg )
          else if (dSeedWindowEnd < dTime) {
            break;
          }  // else if( dSeedWindowEnd < dTime )

          /// Check Seed and build event if needed
Administrator's avatar
Administrator committed
          CheckSeed(dTime, uDigi);
        }  // if( nullptr != pDigi )
      }    // for( UInt_t uDigi = 0; uDigi < uNbRefDigis; ++uDigi )
Administrator's avatar
Administrator committed
    }  // Digi containers controlled by DigiManager
    case ECbmModuleId::kT0: {
      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);
Administrator's avatar
Administrator committed
          Double_t dTime = fT0DigiVec->at(uDigi).GetTime();

          /// Check Seed and build event if needed
Administrator's avatar
Administrator committed
          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!";
      break;
    }  // case ECbmModuleId::kT0
    default: {
      LOG(fatal) << "CbmMcbm2019TimeWinEventBuilderAlgo::LoopOnSeeds => Unknow "
                    "reference detector enum! "
                 << fRefDet;
      break;
    }  // default:
  }    // switch( fRefDet )
Administrator's avatar
Administrator committed
void CbmMcbm2019TimeWinEventBuilderAlgo::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
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
Administrator's avatar
Administrator committed
  if (fdRefTimeWinBeg < fdRefTimeWinEnd) {
    switch (fRefDet) {
      case ECbmModuleId::kSts: {
        SearchMatches<CbmStsDigi>(dSeedTime, fRefDet, fuStartIndexSts);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kSts:
      case ECbmModuleId::kMuch: {
        SearchMatches<CbmMuchBeamTimeDigi>(
          dSeedTime, fRefDet, fuStartIndexMuch);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kMuch:
      case ECbmModuleId::kTrd: {
        SearchMatches<CbmTrdDigi>(dSeedTime, fRefDet, fuStartIndexTrd);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kTrd:
      case ECbmModuleId::kTof: {
        SearchMatches<CbmTofDigi>(dSeedTime, fRefDet, fuStartIndexTof);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kTof:
      case ECbmModuleId::kRich: {
        SearchMatches<CbmRichDigi>(dSeedTime, fRefDet, fuStartIndexRich);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kRich:
      case ECbmModuleId::kPsd: {
        SearchMatches<CbmPsdDigi>(dSeedTime, fRefDet, fuStartIndexPsd);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kPsd:
      case ECbmModuleId::kT0: {
        SearchMatches<CbmTofDigi>(dSeedTime, fRefDet, fuStartIndexT0);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kT0:
      default: {
        LOG(fatal) << "CbmMcbm2019TimeWinEventBuilderAlgo::LoopOnSeeds => "
                   << "Trying to search matches with unsupported det: "
                   << fRefDet;
Administrator's avatar
Administrator committed
      }  // default:
    }    // switch( fRefDet )

    /// Also add the seed if the window starts after the seed
Administrator's avatar
Administrator committed
    if (0 < fdRefTimeWinBeg) AddDigiToEvent(fRefDet, uSeedDigiIdx);
  }  // if( fdRefTimeWinBeg < fdRefTimeWinEnd )
  else {
    AddDigiToEvent(fRefDet, uSeedDigiIdx);
  }  // else of if( fdRefTimeWinBeg < fdRefTimeWinEnd )

  /// Search for matches for each detector in selection list
Administrator's avatar
Administrator committed
  for (std::vector<ECbmModuleId>::iterator det = fvDets.begin();
       det != fvDets.end();
       ++det) {
    switch (*det) {
      case ECbmModuleId::kSts: {
        SearchMatches<CbmStsDigi>(dSeedTime, *det, fuStartIndexSts);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kSts:
      case ECbmModuleId::kMuch: {
        SearchMatches<CbmMuchBeamTimeDigi>(dSeedTime, *det, fuStartIndexMuch);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kMuch:
      case ECbmModuleId::kTrd: {
        SearchMatches<CbmTrdDigi>(dSeedTime, *det, fuStartIndexTrd);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kTrd:
      case ECbmModuleId::kTof: {
        SearchMatches<CbmTofDigi>(dSeedTime, *det, fuStartIndexTof);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kTof:
      case ECbmModuleId::kRich: {
        SearchMatches<CbmRichDigi>(dSeedTime, *det, fuStartIndexRich);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kRich:
      case ECbmModuleId::kPsd: {
        SearchMatches<CbmPsdDigi>(dSeedTime, *det, fuStartIndexPsd);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kPsd:
      case ECbmModuleId::kT0: {
        SearchMatches<CbmTofDigi>(dSeedTime, *det, fuStartIndexT0);
Administrator's avatar
Administrator committed
      }  // case ECbmModuleId::kT0:
      default: {
        LOG(fatal) << "CbmMcbm2019TimeWinEventBuilderAlgo::LoopOnSeeds => "
                   << "Trying to search matches with unsupported det: " << *det;
Administrator's avatar
Administrator committed
      }  // default:
    }    // switch( *det )
  }  // for( std::vector< ECbmModuleId >::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 teh 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) {
      fuStartIndexT0   = fuEndIndexT0;
      fuStartIndexSts  = fuEndIndexSts;
      fuStartIndexMuch = fuEndIndexMuch;
      fuStartIndexTrd  = fuEndIndexTrd;
      fuStartIndexTof  = fuEndIndexTof;
      fuStartIndexRich = fuEndIndexRich;
      fuStartIndexPsd  = fuEndIndexPsd;
Administrator's avatar
Administrator committed
    }  // 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 ) )
Administrator's avatar
Administrator committed
template<class DigiCheck>
void CbmMcbm2019TimeWinEventBuilderAlgo::SearchMatches(Double_t dSeedTime,
                                                       ECbmModuleId detMatch,
                                                       UInt_t& uStartIndex) {
  /// This algo relies on time sorted vectors for the selected detectors
  UInt_t uLocalIndexStart = uStartIndex;
  UInt_t uLocalIndexEnd   = uStartIndex;

  /// FIXME: Use method parameters instead to save 1 switch?
  Double_t dTimeWinBeg = 0;
  Double_t dTimeWinEnd = 0;
Administrator's avatar
Administrator committed
  switch (detMatch) {
    case ECbmModuleId::kSts: {
      dTimeWinBeg = fdStsTimeWinBeg;
      dTimeWinEnd = fdStsTimeWinEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kSts:
    case ECbmModuleId::kMuch: {
      dTimeWinBeg = fdMuchTimeWinBeg;
      dTimeWinEnd = fdMuchTimeWinEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kMuch:
    case ECbmModuleId::kTrd: {
      dTimeWinBeg = fdTrdTimeWinBeg;
      dTimeWinEnd = fdTrdTimeWinEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kTrd:
    case ECbmModuleId::kTof: {
      dTimeWinBeg = fdTofTimeWinBeg;
      dTimeWinEnd = fdTofTimeWinEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kTof:
    case ECbmModuleId::kRich: {
      dTimeWinBeg = fdRichTimeWinBeg;
      dTimeWinEnd = fdRichTimeWinEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kRich:
    case ECbmModuleId::kPsd: {
      dTimeWinBeg = fdPsdTimeWinBeg;
      dTimeWinEnd = fdPsdTimeWinEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kPsd:
    case ECbmModuleId::kT0: {
      dTimeWinBeg = fdT0TimeWinBeg;
      dTimeWinEnd = fdT0TimeWinEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kT0:
    default: {
      LOG(fatal) << "CbmMcbm2019TimeWinEventBuilderAlgo::SearchMatches => "
                 << "Trying to search matches with unsupported det: "
                 << detMatch;
Administrator's avatar
Administrator committed
    }  // default:
  }    // switch( detMatch )

  /// Check the Digis until out of window
Administrator's avatar
Administrator committed
  switch (detMatch) {
    case ECbmModuleId::kSts:
    case ECbmModuleId::kMuch:
    case ECbmModuleId::kTrd:
    case ECbmModuleId::kTof:
    case ECbmModuleId::kRich:
Administrator's avatar
Administrator committed
    case ECbmModuleId::kPsd: {
      UInt_t uNbSelDigis =
        (0 < fDigiMan->GetNofDigis(detMatch) ? fDigiMan->GetNofDigis(detMatch)
                                             : 0);
      /// Loop on size of vector
Administrator's avatar
Administrator committed
      for (UInt_t uDigi = uStartIndex; uDigi < uNbSelDigis; ++uDigi) {
        const DigiCheck* pDigi = fDigiMan->Get<DigiCheck>(uDigi);
        /// Check that _entry is not out of range
Administrator's avatar
Administrator committed
        if (nullptr != pDigi) {
          Double_t dTime     = pDigi->GetTime();
          Double_t dTimeDiff = dTime - dSeedTime;

Administrator's avatar
Administrator committed
          LOG(debug4) << detMatch
                      << Form(" => Checking match %6u / %6u, dt %f",
                              uDigi,
                              uNbSelDigis,
                              dTimeDiff);

          /// Check if within time window, update start/stop indices if needed
Administrator's avatar
Administrator committed
          if (dTimeDiff < dTimeWinBeg) {
            ++uLocalIndexStart;
            continue;
Administrator's avatar
Administrator committed
          }  // if( dTimeDiff < dTimeWinBeg )
          else if (dTimeWinEnd < 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( dTimeWinEnd < dTimeDiff ) of if( dTimeDiff < dTimeWinBeg )

          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
Administrator's avatar
Administrator committed
      if (uLocalIndexEnd < uLocalIndexStart) uLocalIndexEnd = uNbSelDigis;
Administrator's avatar
Administrator committed
    }  // Digi containers controlled by DigiManager
    case ECbmModuleId::kT0: {
      if (fT0DigiVec) {
        /// Loop on size of vector
        UInt_t uNbSelDigis = fT0DigiVec->size();
        /// Loop on size of vector
Administrator's avatar
Administrator committed
        for (UInt_t uDigi = uStartIndex; 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
Administrator's avatar
Administrator committed
          if (dTimeDiff < dTimeWinBeg) {
            ++uLocalIndexStart;
            continue;
Administrator's avatar
Administrator committed
          }  // if( dTimeDiff < dTimeWinBeg )
          else if (dTimeWinEnd < 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( dTimeWinEnd < dTimeDiff ) of if( dTimeDiff < dTimeWinBeg )
Administrator's avatar
Administrator committed
          AddDigiToEvent(detMatch, uDigi);
Administrator's avatar
Administrator committed
          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
Administrator's avatar
Administrator committed
        if (uLocalIndexEnd < uLocalIndexStart) uLocalIndexEnd = uNbSelDigis;
      }  // if ( fT0DigiVec )
      else
        LOG(fatal) << "CbmMcbm2019TimeWinEventBuilderAlgo::SearchMatches => "
                   << "T0 as selection detector but vector not found!";
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kT0
    default: {
Administrator's avatar
Administrator committed
    }  // default:
  }    // switch( detMatch )

  /// Update the StartIndex and EndIndex for the next event seed
Administrator's avatar
Administrator committed
  switch (detMatch) {
    case ECbmModuleId::kSts: {
      fuStartIndexSts = uLocalIndexStart;
      fuEndIndexSts   = uLocalIndexEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kSts:
    case ECbmModuleId::kMuch: {
      fuStartIndexMuch = uLocalIndexStart;
      fuEndIndexMuch   = uLocalIndexEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kMuch:
    case ECbmModuleId::kTrd: {
      fuStartIndexTrd = uLocalIndexStart;
      fuEndIndexTrd   = uLocalIndexEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kTrd:
    case ECbmModuleId::kTof: {
      fuStartIndexTof = uLocalIndexStart;
      fuEndIndexTof   = uLocalIndexEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kTof:
    case ECbmModuleId::kRich: {
      fuStartIndexRich = uLocalIndexStart;
      fuEndIndexRich   = uLocalIndexEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kRich:
    case ECbmModuleId::kPsd: {
      fuStartIndexPsd = uLocalIndexStart;
      fuEndIndexPsd   = uLocalIndexEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kPsd:
    case ECbmModuleId::kT0: {
      fuStartIndexT0 = uLocalIndexStart;
      fuEndIndexT0   = uLocalIndexEnd;
      break;
Administrator's avatar
Administrator committed
    }  // case ECbmModuleId::kT0:
    default: {
Administrator's avatar
Administrator committed
    }  // default:
  }    // switch( detMatch )
Administrator's avatar
Administrator committed
void CbmMcbm2019TimeWinEventBuilderAlgo::AddDigiToEvent(ECbmModuleId _system,
                                                        Int_t _entry) {
  // Fill digi index into event
  switch (_system) {
Administrator's avatar
Administrator committed
    case ECbmModuleId::kMvd:
      fCurrentEvent->AddData(ECbmDataType::kMvdDigi, _entry);
      break;
    case ECbmModuleId::kSts:
      fCurrentEvent->AddData(ECbmDataType::kStsDigi, _entry);
      break;
    case ECbmModuleId::kRich:
      fCurrentEvent->AddData(ECbmDataType::kRichDigi, _entry);
      break;
    case ECbmModuleId::kMuch:
      fCurrentEvent->AddData(ECbmDataType::kMuchDigi, _entry);
      break;
    case ECbmModuleId::kTrd:
      fCurrentEvent->AddData(ECbmDataType::kTrdDigi, _entry);
      break;
    case ECbmModuleId::kTof:
      fCurrentEvent->AddData(ECbmDataType::kTofDigi, _entry);
      break;
    case ECbmModuleId::kPsd:
      fCurrentEvent->AddData(ECbmDataType::kPsdDigi, _entry);
      break;
    case ECbmModuleId::kT0:
      fCurrentEvent->AddData(ECbmDataType::kT0Digi, _entry);
      break;
    default: break;
Administrator's avatar
Administrator committed
Bool_t CbmMcbm2019TimeWinEventBuilderAlgo::HasTrigger(CbmEvent* event) {
  /// Check multiplicity trigger conditions
Administrator's avatar
Administrator committed
  if (CheckTriggerConditions(event, ECbmModuleId::kT0, ECbmDataType::kT0Digi)
      && CheckTriggerConditions(
        event, ECbmModuleId::kSts, ECbmDataType::kStsDigi)
      && CheckTriggerConditions(
        event, ECbmModuleId::kMuch, ECbmDataType::kMuchDigi)
      && CheckTriggerConditions(
        event, ECbmModuleId::kTrd, ECbmDataType::kTrdDigi)
      && CheckTriggerConditions(
        event, ECbmModuleId::kTof, ECbmDataType::kTofDigi)
      && CheckTriggerConditions(
        event, ECbmModuleId::kRich, ECbmDataType::kRichDigi)
      && CheckTriggerConditions(
        event, ECbmModuleId::kPsd, ECbmDataType::kPsdDigi)) {
Administrator's avatar
Administrator committed
  }  // if all trigger conditions fullfilled
  else {
    return kFALSE;
  }  // if at least one trigger condition failed
Administrator's avatar
Administrator committed
Bool_t CbmMcbm2019TimeWinEventBuilderAlgo::CheckTriggerConditions(
  CbmEvent* event,
  ECbmModuleId det,
  ECbmDataType dataType) {
  UInt_t uTrigMin  = 0;
  Int_t iTrigMax   = -1;
  std::string sDet = "";
Administrator's avatar
Administrator committed
  switch (det) {
    case ECbmModuleId::kSts: {
      uTrigMin = fuTriggerMinStsDigis;
      iTrigMax = fiTriggerMaxStsDigis;
Administrator's avatar
Administrator committed
      sDet     = "STS";
Administrator's avatar
Administrator committed
    case ECbmModuleId::kRich: {
      uTrigMin = fuTriggerMinRichDigis;
      iTrigMax = fiTriggerMaxRichDigis;
Administrator's avatar
Administrator committed
      sDet     = "RICH";
Administrator's avatar
Administrator committed
    case ECbmModuleId::kMuch: {
      uTrigMin = fuTriggerMinMuchDigis;
      iTrigMax = fiTriggerMaxMuchDigis;
Administrator's avatar
Administrator committed
      sDet     = "MUCH";
Administrator's avatar
Administrator committed
    case ECbmModuleId::kTrd: {
      uTrigMin = fuTriggerMinTrdDigis;
      iTrigMax = fiTriggerMaxTrdDigis;
Administrator's avatar
Administrator committed
      sDet     = "TRD";
Administrator's avatar
Administrator committed
    case ECbmModuleId::kTof: {
      uTrigMin = fuTriggerMinTofDigis;
      iTrigMax = fiTriggerMaxTofDigis;
Administrator's avatar
Administrator committed
      sDet     = "TOF";
Administrator's avatar
Administrator committed
    case ECbmModuleId::kPsd: {
      uTrigMin = fuTriggerMinPsdDigis;
      iTrigMax = fiTriggerMaxPsdDigis;
Administrator's avatar
Administrator committed
      sDet     = "PSD";
Administrator's avatar
Administrator committed
    case ECbmModuleId::kT0: {
      uTrigMin = fuTriggerMinT0Digis;
      iTrigMax = fiTriggerMaxT0Digis;
Administrator's avatar
Administrator committed
      sDet     = "T0";
Administrator's avatar
Administrator committed
    default: {
      LOG(fatal)
        << "CbmMcbm2019TimeWinEventBuilderAlgo::CheckTriggerConditions => "
        << "Unsupported or unknow detector enum";
Administrator's avatar
Administrator committed
  }  // switch( det )

  /// Check if both Trigger conditions disabled for this detector
Administrator's avatar
Administrator committed
  if (0 == uTrigMin && iTrigMax < 0) {
Administrator's avatar
Administrator committed
  }  // if( 0 == uTrigMin && iTrigMax < 0 )

  /// Check if detector present
Administrator's avatar
Administrator committed
  if (ECbmModuleId::kT0 == det) {
    /// 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 is defined: "
                   << uTrigMin;
      return kFALSE;
    }  // if( !(fT0DigiVec) )
  }    // if( ECbmDataType::kT0Digi == det )
  else {
    if (!fDigiMan->IsPresent(det)) {
      LOG(warning) << "Event does not have digis storage for " << sDet
                   << " while the following trigger minimum is defined: "
                   << uTrigMin;
      return kFALSE;
Administrator's avatar
Administrator committed
    }  // if( !fDigiMan->IsPresent( det ) )
  }    // else of if( ECbmDataType::kT0Digi == det )

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

  /// Check trigger rejection by maximal number
Administrator's avatar
Administrator committed
  if (iNbDigis < iTrigMax) {
Administrator's avatar
Administrator committed
  }  // if( iNbDigis < iTrigMax )
  else {
    LOG(debug2) << "Event Has too many digis: " << iNbDigis << " vs "
                << iTrigMax << " for " << sDet;
    return kFALSE;
  }  // else of if( iNbDigis < iTrigMax )
}

//----------------------------------------------------------------------
Administrator's avatar
Administrator committed
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",
Administrator's avatar
Administrator committed
  fhEventDt   = new TH1F(
    "fhEventDt",
    "interval in seed time of consecutive events; Seed time [s]; Events",
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

  fhNbDigiPerEvtTimeT0 =
    new TH2I("hNbDigiPerEvtTimeT0",
             "nb of T0   digis per event vs seed time of the events; Seed time "
             "[s]; Nb Digis []; Events []",
Administrator's avatar
Administrator committed
  fhNbDigiPerEvtTimeSts =
    new TH2I("hNbDigiPerEvtTimeSts",
             "nb of STS  digis per event vs seed time of the events; Seed time "
             "[s]; Nb Digis []; Events []",
Administrator's avatar
Administrator committed
  fhNbDigiPerEvtTimeMuch =
    new TH2I("hNbDigiPerEvtTimeMuch",
             "nb of MUCH digis per event vs seed time of the events; Seed time "
             "[s]; Nb Digis []; Events []",
Administrator's avatar
Administrator committed
  fhNbDigiPerEvtTimeTrd =
    new TH2I("hNbDigiPerEvtTimeTrd",
             "nb of TRD  digis per event vs seed time of the events; Seed time "
             "[s]; Nb Digis []; Events []",
Administrator's avatar
Administrator committed
  fhNbDigiPerEvtTimeTof =
    new TH2I("hNbDigiPerEvtTimeTof",
             "nb of TOF  digis per event vs seed time of the events; Seed time "
             "[s]; Nb Digis []; Events []",
Administrator's avatar
Administrator committed
  fhNbDigiPerEvtTimeRich =
    new TH2I("hNbDigiPerEvtTimeRich",
             "nb of RICH digis per event vs seed time of the events; Seed time "
             "[s]; Nb Digis []; Events []",
Administrator's avatar
Administrator committed
  fhNbDigiPerEvtTimePsd =
    new TH2I("hNbDigiPerEvtTimePsd",
             "nb of PSD  digis per event vs seed time of the events; Seed time "
             "[s]; Nb Digis []; Events []",
              600, 0,  600,
             4000, 0, 4000);

  AddHistoToVector(fhEventTime,            "evtbuild");
  AddHistoToVector(fhEventDt,              "evtbuild");
  AddHistoToVector(fhEventSize,            "evtbuild");
  AddHistoToVector(fhNbDigiPerEvtTime,     "evtbuild");
  AddHistoToVector(fhNbDigiPerEvtTimeT0,   "evtbuild");
  AddHistoToVector(fhNbDigiPerEvtTimeSts,  "evtbuild");
Administrator's avatar
Administrator committed
  AddHistoToVector(fhNbDigiPerEvtTimeMuch, "evtbuild");
  AddHistoToVector(fhNbDigiPerEvtTimeTrd,  "evtbuild");
  AddHistoToVector(fhNbDigiPerEvtTimeTof,  "evtbuild");
Administrator's avatar
Administrator committed
  AddHistoToVector(fhNbDigiPerEvtTimeRich, "evtbuild");
  AddHistoToVector(fhNbDigiPerEvtTimePsd,  "evtbuild");

  /// FIXME: Re-enable clang formatting after histograms declaration
  /* clang-format on */
Administrator's avatar
Administrator committed
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());

    fhNbDigiPerEvtTimeT0->Fill(evt->GetStartTime() * 1e-9,
                               evt->GetNofData(ECbmDataType::kT0Digi));
    fhNbDigiPerEvtTimeSts->Fill(evt->GetStartTime() * 1e-9,
                                evt->GetNofData(ECbmDataType::kStsDigi));
    fhNbDigiPerEvtTimeMuch->Fill(evt->GetStartTime() * 1e-9,
                                 evt->GetNofData(ECbmDataType::kMuchDigi));
    fhNbDigiPerEvtTimeTrd->Fill(evt->GetStartTime() * 1e-9,
                                evt->GetNofData(ECbmDataType::kTrdDigi));
    fhNbDigiPerEvtTimeTof->Fill(evt->GetStartTime() * 1e-9,
                                evt->GetNofData(ECbmDataType::kTofDigi));
    fhNbDigiPerEvtTimeRich->Fill(evt->GetStartTime() * 1e-9,
                                 evt->GetNofData(ECbmDataType::kRichDigi));
    fhNbDigiPerEvtTimePsd->Fill(evt->GetStartTime() * 1e-9,
                                evt->GetNofData(ECbmDataType::kPsdDigi));

    dPreEvtTime = evt->GetStartTime();
Administrator's avatar
Administrator committed
  }  // for( CbmEvent * evt: fEventVector )
Administrator's avatar
Administrator committed
void CbmMcbm2019TimeWinEventBuilderAlgo::ResetHistograms(
  Bool_t /*bResetTime*/) {
  fhEventTime->Reset();
  fhEventDt->Reset();
  fhEventSize->Reset();
  fhNbDigiPerEvtTime->Reset();
  fhNbDigiPerEvtTimeT0->Reset();
  fhNbDigiPerEvtTimeSts->Reset();
  fhNbDigiPerEvtTimeMuch->Reset();
  fhNbDigiPerEvtTimeTrd->Reset();
  fhNbDigiPerEvtTimeTof->Reset();
  fhNbDigiPerEvtTimeRich->Reset();
  fhNbDigiPerEvtTimePsd->Reset();

  /*
   if( kTRUE == bResetTime )
   {
      /// Also reset the Start time for the evolution plots!
      fdStartTime = -1.0;
   } // if( kTRUE == bResetTime )
*/
}
//----------------------------------------------------------------------
Administrator's avatar
Administrator committed
void CbmMcbm2019TimeWinEventBuilderAlgo::SetReferenceDetector(
  ECbmModuleId refDet) {
  for (std::vector<ECbmModuleId>::iterator det = fvDets.begin();
       det != fvDets.end();
       ++det) {
    if (*det == refDet) {