Skip to content
Snippets Groups Projects
CbmDigiManager.h 5.70 KiB
/* Copyright (C) 2007-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
   SPDX-License-Identifier: GPL-3.0-only
   Authors: Volker Friese [committer], Florian Uhlig */

/** @file CbmDigiManager.h
 ** @author Volker Friese <v.friese@gsi.de>
 ** @since 8 May 2007
 **/


#ifndef CBMDIGIMANAGER_H
#define CBMDIGIMANAGER_H 1

#include "CbmDefs.h"            // for ECbmModuleId
#include "CbmDigiBranchBase.h"  // for CbmDigiBranchBase

#include <FairTask.h>  // for InitStatus
#include <Logger.h>    // for LOG

#include <Rtypes.h>      // for THashConsistencyHolder, Cla...
#include <RtypesCore.h>  // for UInt_t, Bool_t, Int_t, kTRUE

#include <boost/any.hpp>                  // for any_cast, bad_any_cast (ptr...
#include <boost/exception/exception.hpp>  // for clone_impl, error_info_inje...

#include <cassert>  // for assert
#include <gsl/span>
#include <iosfwd>  // for string
#include <map>     // for map, map<>::mapped_type
#include <vector>  // for vector

class CbmMatch;

/** @brief CbmDigiManager
 ** @author Volker Friese <v.friese@gsi.de>
 ** @since 08.05.07
 ** @date 5 June 2019
 **
 ** Interface class to provide access to CbmDigis.
 ** The storage model (STL vector or TClonesArray) is abstracted from.
 **/
class CbmDigiManager {

public:
  /**  Destructor  **/
  virtual ~CbmDigiManager();


  /** @brief Get a digi object
     ** @param  index Index of digi in its container
     ** @return Pointer to constant digi object
     **
     ** Requirement to the template type Digi is that its pointer can be
     ** cast to CbmDigi* and that it has a static method GetSystem().
     **/
  template<class Digi>
  const Digi* Get(Int_t index) const
  {
    assert(fIsInitialised);
    ECbmModuleId system = Digi::GetSystem();
    if (fBranches.find(system) == fBranches.end()) return nullptr;
    try {
      return boost::any_cast<const Digi*>(fBranches[system]->GetDigi(index));
    }
    catch (
      const boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_any_cast>>&) {
      LOG(fatal) << "Failed boost any_cast in Digimanager::Get for a digi of type " << Digi::GetClassName();
    }  // catch only boost::bad_any_cast which can be triggered by CbmMuchDigi/CbmMuchBeamTimeDigi
    return nullptr;
  }

  template<class Digi>
  gsl::span<const Digi> GetArray() const
  {
    assert(fIsInitialised);
    ECbmModuleId system = Digi::GetSystem();

    auto branch = fBranches.find(system);
    if (branch == fBranches.end()) {
      LOG(error) << "Failed to find branch for Digi of type " << Digi::GetClassName();
      return {};
    }

    boost::any container = branch->second->GetBranchContainer();
    LOG_IF(fatal, container.type() != typeid(const std::vector<Digi>*))
      << "Digis of type " << Digi::GetClassName() << " not stored with std::vector";

    return *boost::any_cast<const std::vector<Digi>*>(container);
  }

  /** @brief Access to a digi branch
   ** @param system System identifier
   ** @return Digi branch
   **/
  CbmDigiBranchBase* GetBranch(ECbmModuleId system)
  {
    auto it = fBranches.find(system);
    return (it != fBranches.end() ? it->second : nullptr);
  }


  /** @brief Get a match object
     ** @param  System identifier (ECbmModuleId)
     ** @param  index Index of digi/match in their container
     ** @return Pointer to constant match object
     **/
  const CbmMatch* GetMatch(ECbmModuleId systemId, UInt_t index) const;


  /** Number of digis for a given system
     ** @param  System identifier (ECbmModuleId)
     ** @return Number of digis for system
     **/
  static Int_t GetNofDigis(ECbmModuleId systemId);


  /** @brief Initialisation
     ** @return kSUCCESS is successful
     **
     ** The input tree is checked for digi branches.
     **/
  InitStatus Init();


  /** @brief Static instance **/
  static CbmDigiManager* Instance()
  {
    if (!fgInstance) fgInstance = new CbmDigiManager();
    return fgInstance;
  }


  /** @brief Presence of a digi branch
     ** @param  System identifier (ECbmModuleId)
     ** @return kTRUE if digi branch is present
     **/
  static Bool_t IsPresent(ECbmModuleId systemId);


  /** @brief Presence of a digi match branch
     ** @param  System identifier (ECbmModuleId)
     ** @return kTRUE if digi match branch is present
     **/
  static Bool_t IsMatchPresent(ECbmModuleId systemId);


  /** @brief Set the digi branch name for a system
     ** @param system  System identifier
     ** @param name    Branch name
     **
     ** This can be used if the branch name in the input does
     ** not follow the convention (default).
     **/
  void SetBranchName(ECbmModuleId system, const char* name) { fBranchNames[system] = std::string(name); }


  /** @brief Use CbmMuchBeamTimeDigi instead of CbmMuchDigi for MUCH
     ** @param choice If true, use CbmMuchBeamTimeDigi
     **
     ** Temporary solution until the classes are unified.
     **/
  //void UseMuchBeamTimeDigi(Bool_t choice = kTRUE) { fUseMuchBeamTimeDigi = choice; }
  void UseMuchBeamTimeDigi(Bool_t /*choice = kTRUE*/) { fUseMuchBeamTimeDigi = kFALSE; }
  void UseMuchBeamTimeDigi() { fUseMuchBeamTimeDigi = kFALSE; }

private:
  static std::map<ECbmModuleId, CbmDigiBranchBase*> fBranches;  //!
  static CbmDigiManager* fgInstance;                            //!
  static Bool_t fIsInitialised;
  std::map<ECbmModuleId, std::string> fBranchNames {};
  static Bool_t fUseMuchBeamTimeDigi;


  /**  Default constructor  **/
  CbmDigiManager();


  /** Copy constructor forbidden **/
  CbmDigiManager(const CbmDigiManager&) = delete;


  /** Assignment operator forbidden **/
  CbmDigiManager& operator=(const CbmDigiManager&) = delete;


  /** @brief Set a digi branch **/
  template<class Digi>
  void SetBranch();


  ClassDef(CbmDigiManager, 5);
};


#endif /* CBMDIGIMANAGER_H */