Skip to content
Snippets Groups Projects
CbmTrdDigitizer.cxx 16.1 KiB
Newer Older
/* Copyright (C) 2009-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
   SPDX-License-Identifier: GPL-3.0-only
   Authors: Florian Uhlig [committer], Alexandru Bercuci, Etienne Bechtel */
#include "CbmTrdDigitizer.h"

Administrator's avatar
Administrator committed
#include "CbmMCTrack.h"
#include "CbmMatch.h"
#include "CbmTrdAddress.h"
Administrator's avatar
Administrator committed
#include "CbmTrdCheckUtil.h"
Administrator's avatar
Administrator committed
#include "CbmTrdDigi.h"
#include "CbmTrdGeoHandler.h"
#include "CbmTrdModuleSim.h"
#include "CbmTrdModuleSim2D.h"
#include "CbmTrdPads.h"
Administrator's avatar
Administrator committed
#include "CbmTrdParAsic.h"
#include "CbmTrdParModDigi.h"
#include "CbmTrdParModGain.h"
#include "CbmTrdParModGas.h"
#include "CbmTrdParModGeo.h"
#include "CbmTrdParSetAsic.h"
#include "CbmTrdParSetDigi.h"
#include "CbmTrdParSetGain.h"
Administrator's avatar
Administrator committed
#include "CbmTrdParSetGas.h"
#include "CbmTrdParSetGeo.h"
#include "CbmTrdPoint.h"
Administrator's avatar
Administrator committed
#include "CbmTrdRadiator.h"
Administrator's avatar
Administrator committed
#include "CbmTrdRawToDigiR.h"
Administrator's avatar
Administrator committed
#include <FairBaseParSet.h>
#include <FairEventHeader.h>
Administrator's avatar
Administrator committed
#include <FairRootManager.h>
#include <FairRunAna.h>
Administrator's avatar
Administrator committed
#include <FairRunSim.h>
#include <FairRuntimeDb.h>
Administrator's avatar
Administrator committed
#include <Logger.h>

#include <TClonesArray.h>
Administrator's avatar
Administrator committed
#include <TRandom.h>
#include <TStopwatch.h>
Administrator's avatar
Administrator committed
#include <TVector3.h>
Administrator's avatar
Administrator committed
#include <iomanip>
#include <iostream>
#include <memory>
Administrator's avatar
Administrator committed

#include <cmath>
Administrator's avatar
Administrator committed
using std::pair;
using std::shared_ptr;
using namespace std;
Int_t CbmTrdDigitizer::fConfig = 0;

//________________________________________________________________________________________
CbmTrdDigitizer::CbmTrdDigitizer(shared_ptr<CbmTrdRadiator> radiator)
  : CbmDigitize<CbmTrdDigi>("TrdDigitize")
Administrator's avatar
Administrator committed
  , fLastEventTime(0)
  , fpoints(0)
  , nofBackwardTracks(0)
  , fEfficiency(1.)
  , fPoints(NULL)
  , fTracks(NULL)
  , fDigis(nullptr)
  , fDigiMatches(nullptr)
  , fAsicPar(NULL)
  , fGasPar(NULL)
  , fDigiPar(NULL)
  , fGainPar(NULL)
  , fGeoPar(NULL)
  , fRadiator(radiator)
  , fConverter(NULL)
  , fQA(NULL)
  //  ,fConverter()
  //  ,fGeoHandler(new CbmTrdGeoHandler())
  , fModuleMap()
  if (fRadiator == NULL) fRadiator = make_shared<CbmTrdRadiator>(kTRUE, "tdr18");
//________________________________________________________________________________________
CbmTrdDigitizer::CbmTrdDigitizer(CbmTrdRadiator* radiator)
  : CbmTrdDigitizer(std::make_shared<CbmTrdRadiator>(radiator)) {};


//________________________________________________________________________________________
CbmTrdDigitizer::~CbmTrdDigitizer()
{
  ResetArrays();
  delete fDigis;
  delete fDigiMatches;
  for (map<Int_t, CbmTrdModuleSim*>::iterator imod = fModuleMap.begin(); imod != fModuleMap.end(); imod++)
Administrator's avatar
Administrator committed
    delete imod->second;
  fModuleMap.clear();

  delete fConverter;
  delete fQA;
}


//________________________________________________________________________________________
void CbmTrdDigitizer::SetParContainers()
{
  fAsicPar = static_cast<CbmTrdParSetAsic*>(FairRunAna::Instance()->GetRuntimeDb()->getContainer("CbmTrdParSetAsic"));
  fGasPar  = static_cast<CbmTrdParSetGas*>(FairRunAna::Instance()->GetRuntimeDb()->getContainer("CbmTrdParSetGas"));
  fDigiPar = static_cast<CbmTrdParSetDigi*>(FairRunAna::Instance()->GetRuntimeDb()->getContainer("CbmTrdParSetDigi"));
  fGainPar = static_cast<CbmTrdParSetGain*>(FairRunAna::Instance()->GetRuntimeDb()->getContainer("CbmTrdParSetGain"));
  fGeoPar  = new CbmTrdParSetGeo();  //fGeoPar->Print();
}

//________________________________________________________________________________________
InitStatus CbmTrdDigitizer::Init()
{
  FairRootManager* ioman = FairRootManager::Instance();
  if (!ioman) LOG(fatal) << "CbmTrdDigitizer::Init: No FairRootManager";

  fPoints = (TClonesArray*) ioman->GetObject("TrdPoint");
  if (!fPoints) LOG(fatal) << "CbmTrdDigitizer::Init(): No TrdPoint array!";

Administrator's avatar
Administrator committed
  fTracks = (TClonesArray*) ioman->GetObject("MCTrack");
  if (!fTracks) LOG(fatal) << "CbmTrdDigitizer::Init(): No MCTrack array!";

Administrator's avatar
Administrator committed
  if (fRadiator) fRadiator->Init();

  fConverter = new CbmTrdRawToDigiR();
Administrator's avatar
Administrator committed
  fQA        = new CbmTrdCheckUtil();

  // Set time-based mode if appropriate
  SetTimeBased(fEventMode ? kFALSE : kTRUE);

  RegisterOutput();


  LOG(info) << "================ TRD Digitizer ===============";
Administrator's avatar
Administrator committed
  LOG(info) << " Free streaming    : " << (IsTimeBased() ? "yes" : "no");
  LOG(info) << " Add Noise         : " << (AddNoise() ? "yes" : "no");
  LOG(info) << " Weighted distance : " << (UseWeightedDist() ? "yes" : "no");

  return kSUCCESS;
}

//________________________________________________________________________________________
void CbmTrdDigitizer::Exec(Option_t*)
{
Administrator's avatar
Administrator committed
  TStopwatch timer;
  timer.Start();

  // get event info (once per event, used for matching)
  GetEventInfo();
Administrator's avatar
Administrator committed

  // reset private monitoring counters
  ResetCounters();
Administrator's avatar
Administrator committed

  // loop tracks in current event
Administrator's avatar
Administrator committed
  CbmTrdModuleSim* mod(NULL);
  Int_t nofPoints = fPoints->GetEntriesFast();
  gGeoManager->CdTop();
Administrator's avatar
Administrator committed
  for (Int_t iPoint = 0; iPoint < nofPoints; iPoint++) {
    fpoints++;
    //fMCPointId = iPoint;
Administrator's avatar
Administrator committed

    CbmTrdPoint* point = static_cast<CbmTrdPoint*>(fPoints->At(iPoint));
Administrator's avatar
Administrator committed
    if (!point) continue;
    const CbmMCTrack* track = static_cast<const CbmMCTrack*>(fTracks->At(point->GetTrackID()));
Administrator's avatar
Administrator committed
    if (!track) continue;

    Double_t dz = point->GetZOut() - point->GetZIn();
    if (dz < 0) {
Administrator's avatar
Administrator committed
      LOG(debug2) << GetName() << "::Exec: MC-track points towards target!";
      nofBackwardTracks++;
    }
Administrator's avatar
Administrator committed

    // get link to the module working class
    map<Int_t, CbmTrdModuleSim*>::iterator imod = fModuleMap.find(point->GetDetectorID());
Administrator's avatar
Administrator committed
    if (imod == fModuleMap.end()) {
      // Looking for gas node corresponding to current point in geo manager
      Double_t meanX = (point->GetXOut() + point->GetXIn()) / 2.;
      Double_t meanY = (point->GetYOut() + point->GetYIn()) / 2.;
      Double_t meanZ = (point->GetZOut() + point->GetZIn()) / 2.;
      gGeoManager->FindNode(meanX, meanY, meanZ);
Administrator's avatar
Administrator committed
      if (!TString(gGeoManager->GetPath()).Contains("gas")) {
        LOG(error) << GetName() << "::Exec: MC-track not in TRD! Node:" << TString(gGeoManager->GetPath()).Data()
Administrator's avatar
Administrator committed
                   << " gGeoManager->MasterToLocal() failed!";
        continue;
      }
      mod = AddModule(point->GetDetectorID());
Administrator's avatar
Administrator committed
      mod = imod->second;
    mod->SetLinkId(fCurrentInput, fCurrentMCEntry, iPoint);
    Double_t gamma = TMath::Sqrt(1 + TMath::Power(track->GetP() / (3.e8 * track->GetMass()), 2));
    mod->SetGamma(gamma);
    mod->MakeDigi(point, fCurrentEventTime, TMath::Abs(track->GetPdgCode()) == 11);
  }

  // Fill data from internally used stl map into CbmDaqBuffer.
  // Calculate final event statistics
  Int_t nDigis(0), nofElectrons(0), nofLatticeHits(0), nofPointsAboveThreshold(0), n0, n1, n2;
  for (map<Int_t, CbmTrdModuleSim*>::iterator imod = fModuleMap.begin(); imod != fModuleMap.end(); imod++) {
    // in streaming mode flush buffers only up to a certain point in time wrt to current event time (allow for event pile-ups)
    //printf("Processing data for module %d\n", imod->first);
Administrator's avatar
Administrator committed
    if (IsTimeBased()) nDigis += imod->second->FlushBuffer(fCurrentEventTime);
    // in event-by-event mode flush all buffers
    if (!IsTimeBased()) imod->second->FlushBuffer();
    imod->second->GetCounters(n0, n1, n2);
Administrator's avatar
Administrator committed
    nofElectrons += n0;
    nofLatticeHits += n1;
    nofPointsAboveThreshold += n2;
    std::map<Int_t, std::pair<CbmTrdDigi*, CbmMatch*>>* digis = imod->second->GetDigiMap();
    for (std::map<Int_t, pair<CbmTrdDigi*, CbmMatch*>>::iterator it = digis->begin(); it != digis->end(); it++) {
Administrator's avatar
Administrator committed
      assert(it->second.second);
      CbmTrdDigi* digi = it->second.first;
      SendData(digi->GetTime(), digi, it->second.second);
Administrator's avatar
Administrator committed
    }  //# modules
Administrator's avatar
Administrator committed
  }  //# digis
  fLastEventTime = fCurrentEventTime;


  Double_t digisOverPoints          = (nofPoints > 0) ? Double_t(nDigis) / Double_t(nofPoints) : 0;
  Double_t latticeHitsOverElectrons = (nofElectrons > 0) ? (Double_t) nofLatticeHits / (Double_t) nofElectrons : 0;
  LOG(debug) << "CbmTrdDigitizer::Exec Points:               " << nofPoints;
  LOG(debug) << "CbmTrdDigitizer::Exec PointsAboveThreshold: " << nofPointsAboveThreshold;
  LOG(debug) << "CbmTrdDigitizer::Exec Digis:                " << nDigis;
  LOG(debug) << "CbmTrdDigitizer::Exec digis/points:         " << digisOverPoints;
  LOG(debug) << "CbmTrdDigitizer::Exec BackwardTracks:       " << nofBackwardTracks;
  LOG(debug) << "CbmTrdDigitizer::Exec LatticeHits:          " << nofLatticeHits;
  LOG(debug) << "CbmTrdDigitizer::Exec Electrons:            " << nofElectrons;
  LOG(debug) << "CbmTrdDigitizer::Exec latticeHits/electrons:" << latticeHitsOverElectrons;
  LOG(debug) << "CbmTrdDigitizer::Exec real time=" << timer.RealTime() << " CPU time=" << timer.CpuTime();
  LOG(info) << "+ " << setw(15) << GetName() << ": Event " << setw(6) << right << fCurrentEvent << " at " << fixed
            << setprecision(3) << fCurrentEventTime << " ns, points: " << nofPoints << ", digis: " << nDigis
            << ". Exec time " << setprecision(6) << timer.RealTime() << " s.";
}

//________________________________________________________________________________________
void CbmTrdDigitizer::FlushBuffers()
{
  LOG(info) << GetName() << ": Processing analogue buffers";
  Int_t nDigis(0);
  for (map<Int_t, CbmTrdModuleSim*>::iterator imod = fModuleMap.begin(); imod != fModuleMap.end(); imod++) {
Administrator's avatar
Administrator committed
    nDigis += imod->second->FlushBuffer();
    std::map<Int_t, std::pair<CbmTrdDigi*, CbmMatch*>>* digis = imod->second->GetDigiMap();
    for (std::map<Int_t, pair<CbmTrdDigi*, CbmMatch*>>::iterator it = digis->begin(); it != digis->end(); it++) {
Administrator's avatar
Administrator committed
      assert(it->second.second);
      CbmTrdDigi* digi = it->second.first;
      SendData(digi->GetTime(), digi, it->second.second);
Administrator's avatar
Administrator committed
    }  //# modules
Administrator's avatar
Administrator committed
  }  //# digis
  LOG(info) << GetName() << ": " << nDigis << (nDigis == 1 ? " digi " : " digis ") << "created and sent to DAQ ";
}

//________________________________________________________________________________________
void CbmTrdDigitizer::Finish()
{
Administrator's avatar
Administrator committed
  // flush buffers in streaming mode
  LOG(info) << "=====================================";
  LOG(info) << GetName() << ": Finish run";
Administrator's avatar
Administrator committed
  if (IsTimeBased()) FlushBuffers();
  LOG(info) << GetName() << ": Run summary ";
  LOG(info) << "=====================================";

  fQA->DumpPlots();
}

//________________________________________________________________________________________
CbmTrdModuleSim* CbmTrdDigitizer::AddModule(Int_t detId)
{
Administrator's avatar
Administrator committed
  /**  The geometry structure is treelike with cave as
 * the top node. For the TRD there are keeping volume
 * trd_vXXy_1 which is only container for the different layers.
 * The trd layer is again only a container for all volumes of this layer.
 * Loop over all nodes below the top node (cave). If one of
 * the nodes contains a string trd it must be TRD detector.
 * then over all modules of the layer to extract in the end
 * all active regions (gas) of the complete TRD. For each
 * of the gas volumes get the information about size and
 * position from the geomanager and the sizes of the sectors
 * and pads from the definitions in CbmTrdPads. This info
 * is then stored in a CbmTrdModule object for each of the TRD modules.
Administrator's avatar
Administrator committed
 **/
Administrator's avatar
Administrator committed
  const char* path = gGeoManager->GetPath();
  CbmTrdGeoHandler geoHandler;
  Int_t moduleAddress = geoHandler.GetModuleAddress(path), moduleType = geoHandler.GetModuleType(path),
        orientation = geoHandler.GetModuleOrientation(path), lyId = CbmTrdAddress::GetLayerId(detId);
Administrator's avatar
Administrator committed
  if (moduleAddress != detId) {
    LOG(error) << "CbmTrdDigitizer::AddModule: MC module ID " << detId << " does not match geometry definition "
               << moduleAddress << ". Module init failed!";
  LOG(debug) << GetName() << "::AddModule(" << path << " " << (moduleType < 9 ? 'R' : 'T') << "] mod[" << moduleAddress
Administrator's avatar
Administrator committed
             << "] ly[" << lyId << "] det[" << detId << "]";
  CbmTrdModuleSim* module(NULL);
  if (moduleType >= 9) {
    // temporary fix for TRD-2Dh @ mCBM 2021
    if (moduleType == 10) SetUseFASP(kFALSE);
    else
      SetUseFASP();
    module = fModuleMap[moduleAddress] = new CbmTrdModuleSim2D(moduleAddress, lyId, orientation, UseFASP());
    // AB :: calibration wrt the Tof detector as the T0 simulation is still in development (14.07.2022)
    module->SetTimeSysOffset(-400);
Alexandru Bercuci's avatar
Alexandru Bercuci committed
    if ((rType = geoHandler.GetRadiatorType(path)) >= 0) {
      if (!fRadiator2D) {  // strong TRD-2D entrance window
        //   const Char_t *ewin = "Al;C;Air;C;Al";
        const Char_t* ewin = "Al;C;HC;C;Al";
        Float_t widths[]   = {
          1.2e-3,  // 12 µm aluminized polyester foil
          0.02,    // carbon laminate sheets of 0.2 mm thickness
          0.9,     // 9mm Nomex honeycom
          0.02,    // carbon laminate sheets of 0.2 mm thickness
          1.2e-3,  // 12 µm aluminized polyester foil
        };

        //   // light TRD-2D entrance window
        //   const Char_t *ewin = "Al;C;HC;Po;Al";
        //   Float_t widths[] = {
        //     1.2e-3, // 12 µm aluminized polyester foil
        //     0.02,   // carbon laminate sheets of 0.2 mm thickness
        //     0.9,    // 9mm Nomex honeycom
        //     0.0025, // polyethylen sheets of 50 µm thickness
        //     1.2e-3, // 12 µm aluminized polyester foil
        //   };  pwidth = widths;
        fRadiator2D = make_shared<CbmTrdRadiator>(kTRUE, "tdr18", ewin);
        fRadiator2D->SetEWwidths(5, widths);
        fRadiator2D->Init();
      }
      module->SetRadiator(fRadiator2D);
    }
    //((CbmTrdModuleSim2D*)module)->SetLabMeasurement();
  }
  else {
    module = fModuleMap[moduleAddress] = new CbmTrdModuleSimR(moduleAddress, lyId, orientation);
    module->SetMessageConverter(fConverter);
    module->SetQA(fQA);
  }
Administrator's avatar
Administrator committed

  // try to load Geometry parameters for module
Administrator's avatar
Administrator committed
  const CbmTrdParModGeo* pGeo(NULL);
  if (!fGeoPar || !(pGeo = (const CbmTrdParModGeo*) fGeoPar->GetModulePar(detId))) {
    LOG(debug) << GetName() << "::AddModule : No Geo params for module @ " << path << ". Using default.";
    module->SetGeoPar(new CbmTrdParModGeo(Form("TRD_%d", detId), path));
Administrator's avatar
Administrator committed
    module->SetGeoPar(pGeo);

  // try to load read-out parameters for module
Administrator's avatar
Administrator committed
  const CbmTrdParModDigi* pDigi(NULL);
  if (!fDigiPar || !(pDigi = (const CbmTrdParModDigi*) fDigiPar->GetModulePar(detId))) {
    LOG(debug) << GetName() << "::AddModule : No Read-Out params for module @ " << path << ". Using default.";
  }
  else
Administrator's avatar
Administrator committed
    module->SetDigiPar(pDigi);

  // TODO check if this works also for ModuleR (moduleType < 9) modules
  if (moduleType >= 9) {
    // try to load ASIC parameters for module
Administrator's avatar
Administrator committed
    CbmTrdParSetAsic* pAsic(NULL);
    if (!fAsicPar || !(pAsic = (CbmTrdParSetAsic*) fAsicPar->GetModuleSet(detId))) {
      LOG(debug) << GetName() << "::AddModule : No ASIC params for module @ " << path << ". Using default.";
      module->SetAsicPar();  // map ASIC channels to read-out channels - need ParModDigi already loaded
    }
    else
Administrator's avatar
Administrator committed
      module->SetAsicPar(pAsic);

    // try to load Chamber parameters for module
Administrator's avatar
Administrator committed
    const CbmTrdParModGas* pChmb(NULL);
    if (!fGasPar || !(pChmb = (const CbmTrdParModGas*) fGasPar->GetModulePar(detId))) {
      LOG(debug) << GetName() << "::AddModule : No Gas params for module @ " << path << ". Using default.";
    }
    else
Administrator's avatar
Administrator committed
      module->SetChmbPar(pChmb);

    // try to load Gain parameters for module
Administrator's avatar
Administrator committed
    const CbmTrdParModGain* pGain(NULL);
    if (!fGainPar || !(pGain = (const CbmTrdParModGain*) fGainPar->GetModulePar(detId))) {
      LOG(debug) << GetName() << "::AddModule : No Gain params for module @ " << path << ". Using default.";
    }
    else
Administrator's avatar
Administrator committed
      module->SetGainPar(pGain);
Administrator's avatar
Administrator committed

  if (fRadiator) module->SetRadiator(fRadiator);

  // Register this class to the module. For data transport through SendData().
  module->SetDigitizer(this);


  return module;
}

//________________________________________________________________________________________
void CbmTrdDigitizer::ResetCounters()
{
Administrator's avatar
Administrator committed
  /** Loop over modules and calls ResetCounters on each
Administrator's avatar
Administrator committed
  fpoints           = 0;
  nofBackwardTracks = 0;
  for (std::map<Int_t, CbmTrdModuleSim*>::iterator imod = fModuleMap.begin(); imod != fModuleMap.end(); imod++)
Administrator's avatar
Administrator committed
    imod->second->ResetCounters();
void CbmTrdDigitizer::ResetArrays()
{
Administrator's avatar
Administrator committed
  if (fDigis) fDigis->clear();
  if (fDigiMatches) fDigiMatches->clear();