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"
#include "CbmMCTrack.h"
#include "CbmMatch.h"
#include "CbmTrdAddress.h"
#include "CbmTrdDigi.h"
#include "CbmTrdGeoHandler.h"
#include "CbmTrdModuleSim.h"
#include "CbmTrdModuleSimR.h"
#include "CbmTrdParAsic.h"
#include "CbmTrdParModDigi.h"
#include "CbmTrdParModGain.h"
#include "CbmTrdParModGas.h"
#include "CbmTrdParModGeo.h"
#include "CbmTrdParSetAsic.h"
#include "CbmTrdParSetDigi.h"
#include "CbmTrdParSetGain.h"
#include "CbmTrdParSetGeo.h"
#include "CbmTrdPoint.h"
#include <FairEventHeader.h>
#include <TClonesArray.h>
using namespace std;
Int_t CbmTrdDigitizer::fConfig = 0;
//________________________________________________________________________________________
CbmTrdDigitizer::CbmTrdDigitizer(shared_ptr<CbmTrdRadiator> radiator)
: CbmDigitize<CbmTrdDigi>("TrdDigitize")
, 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++)
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!";
if (!fTracks) LOG(fatal) << "CbmTrdDigitizer::Init(): No MCTrack array!";
fConverter = new CbmTrdRawToDigiR();
// Set time-based mode if appropriate
SetTimeBased(fEventMode ? kFALSE : kTRUE);
RegisterOutput();
LOG(info) << "================ TRD Digitizer ===============";
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*)
{
// get event info (once per event, used for matching)
GetEventInfo();
// reset private monitoring counters
ResetCounters();
// loop tracks in current event
Int_t nofPoints = fPoints->GetEntriesFast();
gGeoManager->CdTop();
fpoints++;
//fMCPointId = iPoint;
CbmTrdPoint* point = static_cast<CbmTrdPoint*>(fPoints->At(iPoint));
const CbmMCTrack* track = static_cast<const CbmMCTrack*>(fTracks->At(point->GetTrackID()));
Double_t dz = point->GetZOut() - point->GetZIn();
if (dz < 0) {
LOG(debug2) << GetName() << "::Exec: MC-track points towards target!";
nofBackwardTracks++;
}
// get link to the module working class
map<Int_t, CbmTrdModuleSim*>::iterator imod = fModuleMap.find(point->GetDetectorID());
// 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);
LOG(error) << GetName() << "::Exec: MC-track not in TRD! Node:" << TString(gGeoManager->GetPath()).Data()
continue;
}
mod = AddModule(point->GetDetectorID());
mod->SetLinkId(fCurrentInput, fCurrentMCEntry, iPoint);
Double_t gamma = TMath::Sqrt(1 + TMath::Power(track->GetP() / (3.e8 * track->GetMass()), 2));
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);
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);
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++) {

Felix Weiglhofer
committed
CbmTrdDigi* digi = it->second.first;
SendData(digi->GetTime(), digi, it->second.second);
} //# 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++) {
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++) {

Felix Weiglhofer
committed
CbmTrdDigi* digi = it->second.first;
SendData(digi->GetTime(), digi, it->second.second);
LOG(info) << GetName() << ": " << nDigis << (nDigis == 1 ? " digi " : " digis ") << "created and sent to DAQ ";
}
//________________________________________________________________________________________
void CbmTrdDigitizer::Finish()
{
LOG(info) << "=====================================";
LOG(info) << GetName() << ": Finish run";
LOG(info) << GetName() << ": Run summary ";
LOG(info) << "=====================================";
fQA->DumpPlots();
}
//________________________________________________________________________________________
CbmTrdModuleSim* CbmTrdDigitizer::AddModule(Int_t detId)
{
* 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.

Felix Weiglhofer
committed
* Now loop over the layers and
* 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.
CbmTrdGeoHandler geoHandler;
Int_t moduleAddress = geoHandler.GetModuleAddress(path), moduleType = geoHandler.GetModuleType(path),
orientation = geoHandler.GetModuleOrientation(path), lyId = CbmTrdAddress::GetLayerId(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
<< "] 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);
Int_t rType(-1);
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);
}
// try to load Geometry parameters for module
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));
// try to load read-out parameters for module
if (!fDigiPar || !(pDigi = (const CbmTrdParModDigi*) fDigiPar->GetModulePar(detId))) {
LOG(debug) << GetName() << "::AddModule : No Read-Out params for module @ " << path << ". Using default.";
}
else
module->SetDigiPar(pDigi);
// TODO check if this works also for ModuleR (moduleType < 9) modules
if (moduleType >= 9) {
// try to load ASIC parameters for module
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
// try to load Chamber parameters for module
if (!fGasPar || !(pChmb = (const CbmTrdParModGas*) fGasPar->GetModulePar(detId))) {
LOG(debug) << GetName() << "::AddModule : No Gas params for module @ " << path << ". Using default.";
}
else
// try to load Gain parameters for module
if (!fGainPar || !(pGain = (const CbmTrdParModGain*) fGainPar->GetModulePar(detId))) {
LOG(debug) << GetName() << "::AddModule : No Gain params for module @ " << path << ". Using default.";
}
else
// Register this class to the module. For data transport through SendData().
module->SetDigitizer(this);
return module;
}
//________________________________________________________________________________________
void CbmTrdDigitizer::ResetCounters()
{
for (std::map<Int_t, CbmTrdModuleSim*>::iterator imod = fModuleMap.begin(); imod != fModuleMap.end(); imod++)
void CbmTrdDigitizer::ResetArrays()
{
if (fDigis) fDigis->clear();
if (fDigiMatches) fDigiMatches->clear();
}
ClassImp(CbmTrdDigitizer)