27#include <FairRootManager.h>
29#include <FairRuntimeDb.h>
31#include <TClonesArray.h>
33#include <TGeoPhysicalNode.h>
39#if __has_include(<omp.h>)
46using std::setprecision;
48using std::stringstream;
56 : FairTask(
"RecoSts", 1)
58 , fWriteClusters(writeClusters)
75 std::vector<cbm::algo::sts::HitfinderPars::Module> gpuModules;
84 Int_t moduleAddress = Int_t(setupModule->
GetAddress());
88 Int_t sensorAddress = Int_t(setupSensor->
GetAddress());
97 Double_t lorentzF = 0.;
98 Double_t lorentzB = 0.;
101 TGeoBBox*
shape =
dynamic_cast<TGeoBBox*
>(setupSensor->
GetPnode()->GetShape());
103 Double_t dZ = 2. *
shape->GetDZ();
107 if (FairRun::Instance()->GetField()) {
108 Double_t local[3] = {0., 0., 0.};
110 setupSensor->
GetPnode()->GetMatrix()->LocalToMaster(local, global);
111 Double_t field[3] = {0., 0., 0.};
112 FairRun::Instance()->GetField()->Field(global, field);
119 lorentzF = lorentzShift.first;
120 lorentzB = lorentzShift.second;
132 auto result =
fModules.insert({moduleAddress, recoModule});
133 assert(result.second);
138 TGeoHMatrix* matrix = recoModule->
getMatrix();
139 std::copy_n(matrix->GetRotationMatrix(), 9, localToGlobal.
rotation.begin());
140 std::copy_n(matrix->GetTranslation(), 3, localToGlobal.
translation.begin());
144 .address = moduleAddress,
146 .pitch = sensPar.
GetPar(6),
147 .stereoF = sensPar.
GetPar(8),
148 .stereoB = sensPar.
GetPar(9),
149 .lorentzF = float(lorentzF),
150 .lorentzB = float(lorentzB),
151 .localToGlobal = localToGlobal,
153 gpuModules.emplace_back(gpuModulePars);
172 std::vector<float> landauValuesF;
173 std::copy(landauValues.begin(), landauValues.end(), std::back_inserter(landauValuesF));
176 .nChannels = nChannels,
177 .modules = gpuModules,
180 .values = landauValuesF,
181 .stepSize = float(landauStepSize),
243 nEvents =
fEvents->GetEntriesFast();
244 LOG(debug) << setw(20) << left << GetName() <<
": Processing time slice " <<
fNofTs <<
" with " << nEvents
245 << (nEvents == 1 ?
" event" :
" events");
246 for (Int_t iEvent = 0; iEvent < nEvents; iEvent++) {
256 logOut << setw(20) << left << GetName() <<
" [";
257 logOut << fixed << setw(8) << setprecision(1) << right << timer.RealTime() * 1000. <<
" ms] ";
258 logOut <<
"TS " <<
fNofTs;
259 if (
fEvents) logOut <<
", events " << nEvents;
262 LOG(info) << logOut.str();
287 ompThreads = omp_get_max_threads();
292 LOG(info) <<
"=====================================";
293 LOG(info) << GetName() <<
": Run summary";
295 LOG(info) <<
"Ran new GPU STS reconstruction. (Device " << xpu::device_prop(xpu::device::active()).name() <<
")";
296 else if (ompThreads < 0)
297 LOG(info) <<
"STS reconstruction ran single threaded (No OpenMP).";
299 LOG(info) <<
"STS reconstruction ran multithreaded with OpenMP (nthreads = " << ompThreads <<
")";
300 LOG(info) <<
"Time slices : " <<
fNofTs;
302 LOG(info) <<
"Digis / TSlice : " << fixed << setprecision(2) <<
fNofDigisRun / Double_t(
fNofTs);
303 LOG(info) <<
"Digis used / TSlice : " << fixed << setprecision(2) <<
fNofDigisUsed / Double_t(
fNofTs);
304 LOG(info) <<
"Digis ignored / TSlice : " << fixed << setprecision(2) <<
fNofDigisIgnored / Double_t(
fNofTs);
305 LOG(info) <<
"Clusters / TSlice : " << fixed << setprecision(2) <<
fNofClusters / Double_t(
fNofTs);
306 LOG(info) <<
"Hits / TSlice : " << fixed << setprecision(2) <<
fNofHits / Double_t(
fNofTs);
307 LOG(info) <<
"Digis per cluster : " << fixed << setprecision(2) << digiCluster;
308 LOG(info) <<
"Clusters per hit : " << fixed << setprecision(2) << clusterHit;
309 LOG(info) <<
"Time per TSlice : " << fixed << setprecision(2) << 1000. *
fTimeRun / Double_t(
fNofTs) <<
" ms ";
315 auto moduleTime = m->GetTimings();
317 timingsTotal.
timeCluster += moduleTime.timeCluster;
319 timingsTotal.
timeHits += moduleTime.timeHits;
331 auto throughput = [](
auto bytes,
auto timeMs) {
return bytes * 1000. / timeMs / double(1ull << 30); };
335 LOG(info) <<
"Time Reset : " << fixed << setprecision(1) << setw(6) << 1000. *
fTime1 <<
" ms ("
336 << setprecision(1) << setw(4) << 100. *
fTime1 /
fTimeTot <<
" %)";
337 LOG(info) <<
"Time Distribute : " << fixed << setprecision(1) << setw(6) << 1000. *
fTime2 <<
" ms ("
339 LOG(info) <<
"Time Reconstruct: " << fixed << setprecision(1) << setw(6) << 1000. *
fTime3 <<
" ms ("
340 << setprecision(1) << setw(4) << 100. *
fTime3 /
fTimeTot <<
" %)";
341 LOG(info) <<
"Time by step:\n"
342 <<
" Sort Digi : " << fixed << setprecision(2) << setw(6) << 1000. *
fTimeSortDigis <<
" ms ("
344 <<
" Find Cluster: " << fixed << setprecision(2) << setw(6) << 1000. *
fTimeFindClusters <<
" ms ("
346 <<
" Sort Cluster: " << fixed << setprecision(2) << setw(6) << 1000. *
fTimeSortClusters <<
" ms ("
348 <<
" Find Hits : " << fixed << setprecision(2) << setw(6) << 1000. *
fTimeFindHits <<
" ms ("
352 LOG(warn) <<
"Hitfinder times collected by cbm::algo::Reco";
373 LOG(info) <<
"=====================================";
383 std::cout << std::endl;
384 LOG(info) <<
"==========================================================";
385 LOG(info) << GetName() <<
": Initialising ";
391 setenv(
"XPU_PROFILE",
"1", 1);
396 FairRootManager* ioman = FairRootManager::Instance();
405 LOG(info) << GetName() <<
": Using event-by-event mode";
406 fEvents =
dynamic_cast<TClonesArray*
>(ioman->GetObject(
"CbmEvent"));
408 LOG(warn) << GetName() <<
": Event mode selected but no event array found!";
413 LOG(info) << GetName() <<
": Using time-based mode";
419 fClusters =
new TClonesArray(
"CbmStsCluster", 1);
420 ioman->Register(
"StsCluster",
"Clusters in STS",
fClusters, IsOutputBranchPersistent(
"StsCluster"));
423 fHits =
new TClonesArray(
"CbmStsHit", 1);
424 ioman->Register(
"StsHit",
"Hits in STS",
fHits, IsOutputBranchPersistent(
"StsHit"));
440 LOG(info) << GetName() <<
": Created " << nModules <<
" modules";
442 LOG(info) << GetName() <<
": Initialisation successful.";
443 LOG(info) <<
"==========================================================";
455 TString sourceModu =
"database";
462 sourceModu =
"user-defined";
469 sourceModu =
"user-defined, global";
471 LOG(info) << GetName() <<
": Module parameters (" << sourceModu <<
") " <<
fParSetModule->
ToString();
474 TString sourceSens =
"database";
481 sourceSens =
"user-defined";
488 sourceSens =
"user-defined, global";
490 LOG(info) << GetName() <<
": Sensor parameters (" << sourceSens <<
") " <<
fParSetSensor->
ToString();
493 TString sourceCond =
"database";
500 sourceSens =
"user-defined";
507 sourceCond =
"user-defined, global";
509 LOG(info) << GetName() <<
": Sensor conditions (" << sourceCond <<
")" <<
fParSetCond->
ToString();
516 LOG_IF(warn, useGpu) <<
"CbmRecoSts: GPU STS reconstruction temporarily disabled! Will use CPU reco instead.";
526 Double_t vBias = conditions.
GetVbias();
527 Double_t vFd = conditions.
GetVfd();
528 Double_t eField = (vBias + vFd) / dZ;
532 Double_t deltaZ = dZ / nSteps;
533 Double_t dxMeanE = 0.;
534 Double_t dxMeanH = 0.;
535 for (Int_t j = 0; j <= nSteps; j++) {
536 eField -= 2 * vFd / dZ * deltaZ / dZ;
539 dxMeanE += muHallE * (dZ - Double_t(j) * deltaZ);
540 dxMeanH += muHallH * Double_t(j) * deltaZ;
542 dxMeanE /= Double_t(nSteps);
543 dxMeanH /= Double_t(nSteps);
544 Double_t shiftF = dxMeanE * bY * 1.e-4;
545 Double_t shiftB = dxMeanH * bY * 1.e-4;
549 return {shiftF, shiftB};
560 Int_t nDigisIgnored = 0;
565#pragma omp parallel for schedule(static)
571 Double_t time1 =
fTimer.RealTime();
580 for (Int_t iDigi = 0; iDigi < nDigis; iDigi++) {
593 auto it =
fModules.find(moduleAddress);
601 module->AddDigiToQueue(digi, digiIndex);
604 Double_t time2 =
fTimer.RealTime();
610 TStopwatch timeSubstep;
614#pragma omp parallel for schedule(static)
625#pragma omp parallel for schedule(static)
636#pragma omp parallel for schedule(static)
647#pragma omp parallel for schedule(static)
657 Double_t time3 =
fTimer.RealTime();
666 ULong64_t offsetClustersF = 0;
667 ULong64_t offsetClustersB = 0;
670 const vector<CbmStsCluster>& moduleClustersF =
fModuleIndex[it]->GetClustersF();
672 offsetClustersF =
fClusters->GetEntriesFast();
673 for (
auto& cluster : moduleClustersF) {
674 UInt_t index =
fClusters->GetEntriesFast();
680 const vector<CbmStsCluster>& moduleClustersB =
fModuleIndex[it]->GetClustersB();
682 offsetClustersB =
fClusters->GetEntriesFast();
683 for (
auto& cluster : moduleClustersB) {
684 UInt_t index =
fClusters->GetEntriesFast();
690 const vector<CbmStsHit>& moduleHits =
fModuleIndex[it]->GetHits();
691 for (
auto& hit : moduleHits) {
692 UInt_t index =
fHits->GetEntriesFast();
701 Double_t time4 =
fTimer.RealTime();
704 Double_t realTime = time1 + time2 + time3 + time4;
718 LOG(debug) << setw(20) << left << GetName() <<
"[" << fixed << setprecision(4) << realTime <<
" s] : Event "
719 << right << setw(6) <<
event->GetNumber() <<
", digis: " << nDigis <<
", ignored: " << nDigisIgnored
720 <<
", clusters: " << nClusters <<
", hits " << nHits;
723 LOG(debug) << setw(20) << left << GetName() <<
"[" << fixed << setprecision(4) << realTime <<
" s] : TSlice "
724 << right << setw(6) <<
fNofTs <<
", digis: " << nDigis <<
", ignored: " << nDigisIgnored
725 <<
", clusters: " << nClusters <<
", hits " << nHits;
733 throw std::runtime_error(
"STS GPU Reco does not yet support event-by-event mode.");
748 size_t nClustersForwarded = 0, nHitsForwarded = 0;
750 const cbm::algo::StsHitfinderHost& hfc =
fGpuReco.GetHitfinderBuffers();
753 for (
int module = 0;
module < hfc.nModules;
module++) {
755 auto* gpuClusterF = &hfc.clusterDataPerModule.h()[module * hfc.maxClustersPerModule];
756 auto* gpuClusterIdxF = &hfc.clusterIdxPerModule.h()[module * hfc.maxClustersPerModule];
757 int nClustersFGpu = hfc.nClustersPerModule.h()[module];
759 nClustersForwarded += nClustersFGpu;
761 for (
int i = 0; i < nClustersFGpu; i++) {
762 auto& cidx = gpuClusterIdxF[i];
763 auto& clusterGpu = gpuClusterF[cidx.fIdx];
765 unsigned int outIdx =
fClusters->GetEntriesFast();
768 clusterOut->
SetAddress(pars.modules[module].address);
769 clusterOut->SetProperties(clusterGpu.fCharge, clusterGpu.fPosition, clusterGpu.fPositionError, cidx.fTime,
770 clusterGpu.fTimeError);
771 clusterOut->SetSize(clusterGpu.fSize);
774 auto* gpuClusterB = &hfc.clusterDataPerModule.h()[(module + hfc.nModules) * hfc.maxClustersPerModule];
775 auto* gpuClusterIdxB = &hfc.clusterIdxPerModule.h()[(module + hfc.nModules) * hfc.maxClustersPerModule];
776 int nClustersBGpu = hfc.nClustersPerModule.h()[module + hfc.nModules];
778 nClustersForwarded += nClustersBGpu;
780 for (
int i = 0; i < nClustersBGpu; i++) {
781 auto& cidx = gpuClusterIdxB[i];
782 auto& clusterGpu = gpuClusterB[cidx.fIdx];
783 unsigned int outIdx =
fClusters->GetEntriesFast();
786 clusterOut->
SetAddress(pars.modules[module].address);
787 clusterOut->SetProperties(clusterGpu.fCharge, clusterGpu.fPosition, clusterGpu.fPositionError, cidx.fTime,
788 clusterGpu.fTimeError);
789 clusterOut->SetSize(clusterGpu.fSize);
792 auto* gpuHits = &hfc.hitsPerModule.h()[module * hfc.maxHitsPerModule];
793 int nHitsGpu = hfc.nHitsPerModule.h()[module];
795 nHitsForwarded += nHitsGpu;
797 for (
int i = 0; i < nHitsGpu; i++) {
798 auto& hitGpu = gpuHits[i];
800 unsigned int outIdx =
fHits->GetEntriesFast();
801 new ((*fHits)[outIdx])
::CbmStsHit {pars.modules[module].address,
802 TVector3 {hitGpu.fX, hitGpu.fY, hitGpu.fZ},
803 TVector3 {hitGpu.fDx, hitGpu.fDy, hitGpu.fDz},
807 double(hitGpu.fTime),
815 return {nClustersForwarded, nHitsForwarded};
824 FairRuntimeDb* db = FairRun::Instance()->GetRuntimeDb();
834 LOG(warn) <<
"DumpNewHits() not implemented yet";
851 std::ofstream out{
"oldHits.csv"};
853 out <<
"module, x, y, z, deltaX, deltaY, deltaZ, deltaXY, time, timeError, deltaU, deltaV" << std::endl;
858 for (
const auto&
h :
hits) {
859 out << m <<
", " <<
h.GetX() <<
", " <<
h.GetY() <<
", " <<
h.GetZ() <<
", " <<
h.GetDx() <<
", " <<
h.GetDy()
860 <<
", " <<
h.GetDz() <<
", " <<
h.GetDxy() <<
", " <<
h.GetTime() <<
", " <<
h.GetTimeError() <<
", "
861 <<
h.GetDu() <<
", " <<
h.GetDv() << std::endl;
ECbmRecoMode
Reconstruct the full time slice or event-by-event.
XPU_D constexpr auto ToIntegralType(T enumerator) -> typename std::underlying_type< T >::type
@ kSts
Silicon Tracking System.
static vector< vector< QAHit > > hits
static int32_t GetSystemId(uint32_t address)
void SetAddress(int32_t address)
gsl::span< const Digi > GetArray() const
static Int_t GetNofDigis(ECbmModuleId systemId)
static Bool_t IsPresent(ECbmModuleId systemId)
Presence of a digi branch.
InitStatus Init()
Initialisation.
static CbmDigiManager * Instance()
Static instance.
Class characterising one event by a collection of links (indices) to data objects,...
Task class for local reconstruction in the STS.
Long64_t fNofDigisUsed
Total number of used digis.
Double_t fTime2
Time for distributing data.
Double_t fTimeCutClustersSig
Time cut for hit finding.
CbmRecoSts(ECbmRecoMode mode=ECbmRecoMode::Timeslice, Bool_t writeClusters=kFALSE)
Constructor.
CbmStsParSetSensorCond * fParSetCond
Sensor conditions.
CbmStsParSetSensor * fParSetSensor
Sensor parameters.
Double_t fTimeCutClustersAbs
Time cut for hit finding [ns].
CbmStsParSetSensor * fUserParSetSensor
cbm::algo::sts::HitfinderChain fGpuReco
Double_t fNofDigisRun
Total number of digis processed.
CbmStsParSim * fParSim
Instance of STS setup.
void InitParams()
Initialise parameters.
ECbmRecoMode fMode
Time-slice or event-by-event.
std::map< UInt_t, CbmStsRecoModule * > fModules
CbmStsSetup * fSetup
Output hit array.
Double_t fTime1Run
Time for resetting modules.
CbmStsParSetModule * fUserParSetModule
std::pair< Double_t, Double_t > LorentzShift(const CbmStsParSensorCond &conditions, Double_t dZ, Double_t bY)
Average Lorentz Shift in a sensor.
Long64_t fNofDigisIgnored
Total number of ignored digis.
Double_t fNofHitsRun
Total number of clusters produced.
void SetUseGpuReco(bool useGPU)
std::vector< CbmStsRecoModule * > fModuleIndex
Int_t fNofEvents
Number of events processed.
TClonesArray * fClusters
Interface to digi branch.
Double_t fTime1
Time for resetting modules.
CbmStsParSensorCond * fUserParCond
UInt_t CreateModules()
Instantiate reconstruction modules @value Number of modules created.
TClonesArray * fHits
Output cluster array.
CbmDigiManager * fDigiManager
Input array of events.
Double_t fTimeCutDigisSig
Time cut for cluster finding.
CbmStsParSetModule * fParSetModule
Module parameters.
Double_t fTime4Run
Time for output results.
Double_t fTime3
Time for reconstruction.
Double_t fNofDigisUsedRun
Total number of used digis.
CbmStsParSensor * fUserParSensor
Long64_t fNofHits
Total number of clusters produced.
Double_t fTimeTot
Total execution time.
Long64_t fNofDigis
Total number of digis processed.
Double_t fTime2Run
Time for distributing data.
Double_t fTimeCutDigisAbs
Time cut for cluster finding [ns].
Double_t fTimeRun
Total execution time.
Long64_t fNofClusters
Total number of clusters produced.
virtual ~CbmRecoSts()
Destructor
virtual InitStatus Init()
Initialisation.
Double_t fTime4
Time for output results.
virtual void SetParContainers()
Define the needed parameter containers.
Double_t fNofClustersRun
Total number of clusters produced.
std::pair< size_t, size_t > ForwardGpuClusterAndHits()
CbmStsParSetSensorCond * fUserParSetCond
CbmStsParModule * fUserParModule
virtual void Exec(Option_t *opt)
Task execution.
virtual void Finish()
End-of-run action.
Double_t fTime3Run
Time for reconstruction.
void ProcessData(CbmEvent *event=nullptr)
Process one time slice or event.
Data class for STS clusters.
Data class for a single-channel message in the STS.
XPU_D int32_t GetAddress() const
Class representing an element of the STS setup.
TGeoPhysicalNode * GetPnode() const
Int_t GetNofDaughters() const
CbmStsElement * GetDaughter(Int_t index) const
data class for a reconstructed 3-d hit in the STS
int32_t GetFrontClusterId() const
void SetFrontClusterId(int32_t index)
Set the index of the frontside cluster To keep track of the input during matching.
void SetBackClusterId(int32_t index)
Set the index of the backside cluster To keep track of the input during matching.
int32_t GetBackClusterId() const
Class representing an instance of a readout unit in the CBM-STS.
Parameters of the STS readout ASIC.
double GetDynRange() const
Dynamic range of ADC.
uint16_t GetNofAdc() const
Number of ADC channels.
double GetZeroNoiseRate() const
Zero-crossing noise rate.
double GetNoise() const
Electronic noise RMS.
double GetThreshold() const
ADC Threshold.
double GetTimeResol() const
Time resolution.
double GetDeadTime() const
Single-channel dead time.
Parameters for one STS module.
uint32_t GetNofChannels() const
Number of channels.
const CbmStsParAsic & GetParAsic(uint32_t channel) const
ASIC parameters for a given channel.
Parameters for operating conditions of a STS sensor.
Double_t GetVbias() const
Bias voltage.
Double_t GetHallMobility(Double_t eField, Int_t chargeType) const
Hall mobility.
Constructional parameters of a STS sensor.
Float_t GetPar(UInt_t index) const
Get a parameter.
Parameters container for CbmStsParModule.
void SetGlobalPar(const CbmStsParModule ¶ms)
Set global parameters (for all modules)
const CbmStsParModule & GetParModule(UInt_t address)
Get condition parameters of a sensor.
virtual void clear()
Reset all parameters.
std::string ToString() const
Info to string.
Parameters container for CbmStsParSensorCond.
std::string ToString()
Info to string.
void SetGlobalPar(Double_t vDep, Double_t vBias, Double_t temperature, Double_t cCoupling, Double_t cInterstrip)
Set global conditions (for all sensors)
virtual void clear()
Reset all parameters.
const CbmStsParSensorCond & GetParSensor(UInt_t address)
Get condition parameters of a sensor.
Parameters container for CbmStsParSensor.
std::string ToString() const
Info to string.
void SetGlobalPar(const CbmStsParSensor ¶ms)
Set global parameters (for all modules)
const CbmStsParSensor & GetParSensor(UInt_t address)
Get condition parameters of a sensor.
virtual void clear()
Reset all parameters.
Settings for STS simulation (digitizer)
Bool_t LorentzShift() const
Check whether Lorentz shift is applied.
std::string ToString() const
String output.
std::pair< std::vector< double >, double > GetLandauWidthTable() const
Raw values of landau width interpolation table.
static CbmStsPhysics * Instance()
Accessor to singleton instance.
Class for reconstruction in one STS module.
TGeoHMatrix * getMatrix()
void SetTimeCutDigisAbs(Double_t value)
Time cut on digis for cluster finding.
void SetTimeCutClustersAbs(Double_t value)
Time cut on clusters for hit finding.
void SetTimeCutClustersSig(Double_t value)
Time cut on clusters for hit finding.
void SetTimeCutDigisSig(Double_t value)
Time cut on digis for hit finding.
Bool_t Init(const char *geometryFile=nullptr)
Initialise the setup.
CbmStsModule * GetModule(Int_t index) const
Get a module from the module array.
static CbmStsSetup * Instance()
Int_t GetNofModules() const
Data class with information on a STS local track.
const HitfinderChainPars & GetParameters() const
void SetParameters(const HitfinderChainPars ¶meters)
int32_t GetMotherAddress(int32_t address, int32_t level)
Construct the address of an element from the address of a descendant element.
std::string ToString(int32_t address)
String output.