CbmRoot
Loading...
Searching...
No Matches
CbmRecoSts.cxx
Go to the documentation of this file.
1/* Copyright (C) 2020-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Volker Friese [committer] */
4
10#include "CbmRecoSts.h"
11
12#include "CbmAddress.h"
13#include "CbmDigiManager.h"
14#include "CbmEvent.h"
15#include "CbmStsDigi.h"
16#include "CbmStsModule.h"
17#include "CbmStsParSetModule.h"
18#include "CbmStsParSetSensor.h"
20#include "CbmStsParSim.h"
21#include "CbmStsPhysics.h"
22#include "CbmStsRecoModule.h"
23#include "CbmStsSetup.h"
24#include "sts/HitfinderPars.h"
25
26#include <FairField.h>
27#include <FairRootManager.h>
28#include <FairRun.h>
29#include <FairRuntimeDb.h>
30
31#include <TClonesArray.h>
32#include <TGeoBBox.h>
33#include <TGeoPhysicalNode.h>
34
35#include <iomanip>
36
37#include <xpu/host.h>
38
39#if __has_include(<omp.h>)
40#include <omp.h>
41#endif
42
43using std::fixed;
44using std::left;
45using std::right;
46using std::setprecision;
47using std::setw;
48using std::stringstream;
49using std::vector;
50
51
53
54// ----- Constructor ---------------------------------------------------
55CbmRecoSts::CbmRecoSts(ECbmRecoMode mode, Bool_t writeClusters)
56 : FairTask("RecoSts", 1)
57 , fMode(mode)
58 , fWriteClusters(writeClusters)
59{
60}
61// -------------------------------------------------------------------------
62
63
64// ----- Destructor ----------------------------------------------------
66// -------------------------------------------------------------------------
67
68
69// ----- Initialise the cluster finding modules ------------------------
71{
72
73 assert(fSetup);
74
75 std::vector<cbm::algo::sts::HitfinderPars::Module> gpuModules; // for gpu reco
76 // std::vector<int> moduleAddrs;
77 // std::vector<experimental::CbmStsHitFinderConfig> hfCfg;
78
79 for (Int_t iModule = 0; iModule < fSetup->GetNofModules(); iModule++) {
80
81 // --- Setup module and sensor
82 CbmStsModule* setupModule = fSetup->GetModule(iModule);
83 assert(setupModule);
84 Int_t moduleAddress = Int_t(setupModule->GetAddress());
85 assert(setupModule->GetNofDaughters() == 1);
86 CbmStsElement* setupSensor = setupModule->GetDaughter(0);
87 assert(setupSensor);
88 Int_t sensorAddress = Int_t(setupSensor->GetAddress());
89
90 // --- Module parameters
91 const CbmStsParModule& modPar = fParSetModule->GetParModule(moduleAddress);
92 const CbmStsParSensor& sensPar = fParSetSensor->GetParSensor(sensorAddress);
93 const CbmStsParSensorCond& sensCond = fParSetCond->GetParSensor(sensorAddress);
94
95 // --- Calculate and set average Lorentz shift
96 // --- This will be used in hit finding for correcting the position.
97 Double_t lorentzF = 0.;
98 Double_t lorentzB = 0.;
99 if (fParSim->LorentzShift()) {
100
101 TGeoBBox* shape = dynamic_cast<TGeoBBox*>(setupSensor->GetPnode()->GetShape());
102 assert(shape);
103 Double_t dZ = 2. * shape->GetDZ(); // Sensor thickness
104
105 // Get the magnetic field in the sensor centre
106 Double_t by = 0.;
107 if (FairRun::Instance()->GetField()) {
108 Double_t local[3] = {0., 0., 0.}; // sensor centre in local C.S.
109 Double_t global[3]; // sensor centre in global C.S.
110 setupSensor->GetPnode()->GetMatrix()->LocalToMaster(local, global);
111 Double_t field[3] = {0., 0., 0.}; // magnetic field components
112 FairRun::Instance()->GetField()->Field(global, field);
113 by = field[1] / 10.; // kG->T
114 } //? field present
115
116 // Calculate average Lorentz shift on sensor sides.
117 // This is needed in hit finding for correcting the cluster position.
118 auto lorentzShift = LorentzShift(sensCond, dZ, by);
119 lorentzF = lorentzShift.first;
120 lorentzB = lorentzShift.second;
121 } //? Lorentz-shift correction
122
123 // --- Create reco module
124 CbmStsRecoModule* recoModule = new CbmStsRecoModule(setupModule, modPar, sensPar, lorentzF, lorentzB);
125 assert(recoModule);
126
131
132 auto result = fModules.insert({moduleAddress, recoModule});
133 assert(result.second);
134 fModuleIndex.push_back(recoModule);
135
136 // Get Transformation Matrix
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());
141
142 // Collect GPU parameters
144 .address = moduleAddress,
145 .dY = sensPar.GetPar(3),
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,
152 };
153 gpuModules.emplace_back(gpuModulePars);
154 }
155
156 const CbmStsParModule& firstModulePars = fParSetModule->GetParModule(gpuModules[0].address);
157
158 CbmStsParAsic asic = firstModulePars.GetParAsic(0);
160 .nAdc = asic.GetNofAdc(),
161 .dynamicRange = float(asic.GetDynRange()),
162 .threshold = float(asic.GetThreshold()),
163 .timeResolution = float(asic.GetTimeResol()),
164 .deadTime = float(asic.GetDeadTime()),
165 .noise = float(asic.GetNoise()),
166 .zeroNoiseRate = float(asic.GetZeroNoiseRate()),
167 };
168
169 int nChannels = firstModulePars.GetNofChannels();
170
171 auto [landauValues, landauStepSize] = CbmStsPhysics::Instance()->GetLandauWidthTable();
172 std::vector<float> landauValuesF;
173 std::copy(landauValues.begin(), landauValues.end(), std::back_inserter(landauValuesF));
175 .asic = algoAsic,
176 .nChannels = nChannels,
177 .modules = gpuModules,
178 .landauTable =
179 {
180 .values = landauValuesF,
181 .stepSize = float(landauStepSize),
182 },
183 };
185 .setup = pars,
186 .memory = {},
187 };
188 if (fUseGpuReco) fGpuReco.SetParameters(chainPars);
189
190 return fModules.size();
191}
192// -------------------------------------------------------------------------
193
194
195// ----- Task execution ------------------------------------------------
196void CbmRecoSts::Exec(Option_t*)
197{
198
199 // --- Time
200 TStopwatch timer;
201 timer.Start();
202
203 // --- Clear hit output array
204 fHits->Delete();
205
206 // --- Reset cluster output array
207 fClusters->Delete();
208
209 // --- Local variables
210 Int_t nEvents = 0;
211 fNofDigis = 0;
212 fNofDigisUsed = 0;
214 fNofClusters = 0;
215 fNofHits = 0;
216 fTimeTot = 0.;
217 fTime1 = 0.;
218 fTime2 = 0.;
219 fTime3 = 0.;
220 fTime4 = 0.;
221 CbmEvent* event = nullptr;
222
223 // --- Time-slice mode: process entire array
224
225 if (fUseGpuReco) {
226
228 // fNofDigis = fGpuReco.nDigis;
229 // fNofDigisUsed = fGpuReco.nDigisUsed;
230 // fNofClusters = fGpuReco.nCluster;
231 // fNofHits = fGpuReco.nHits;
232
233 // Old reco in time based mode
234 }
235 else if (fMode == ECbmRecoMode::Timeslice) {
236
237 ProcessData(nullptr);
238
239 // --- Event mode: loop over events
240 }
241 else {
242 assert(fEvents);
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++) {
247 event = dynamic_cast<CbmEvent*>(fEvents->At(iEvent));
248 assert(event);
249 ProcessData(event);
250 } //# events
251 } //? event mode
252
253 // --- Timeslice log
254 timer.Stop();
255 stringstream logOut;
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;
260 logOut << ", digis " << fNofDigisUsed << " / " << fNofDigis;
261 logOut << ", clusters " << fNofClusters << ", hits " << fNofHits;
262 LOG(info) << logOut.str();
263
264 // --- Update run counters
265 fNofTs++;
266 fNofEvents += nEvents;
272 fTime1Run += fTime1;
273 fTime2Run += fTime2;
274 fTime3Run += fTime3;
275 fTime4Run += fTime4;
276
277 // allDigis = fNofDigisUsed;
278}
279// -------------------------------------------------------------------------
280
281
282// ----- End-of-run action ---------------------------------------------
284{
285 int ompThreads = -1;
286#ifdef _OPENMP
287 ompThreads = omp_get_max_threads();
288#endif
289
290 Double_t digiCluster = Double_t(fNofDigisUsed) / Double_t(fNofClusters);
291 Double_t clusterHit = Double_t(fNofClusters) / Double_t(fNofHits);
292 LOG(info) << "=====================================";
293 LOG(info) << GetName() << ": Run summary";
294 if (fUseGpuReco)
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).";
298 else
299 LOG(info) << "STS reconstruction ran multithreaded with OpenMP (nthreads = " << ompThreads << ")";
300 LOG(info) << "Time slices : " << fNofTs;
301 if (fMode == ECbmRecoMode::EventByEvent) LOG(info) << "Events : " << fNofEvents;
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 ";
310
311 // Aggregate times for substeps of reconstruction
312 // Note: These times are meaningless when reconstruction runs with > 1 thread.
313 CbmStsRecoModule::Timings timingsTotal;
314 for (const auto* m : fModuleIndex) {
315 auto moduleTime = m->GetTimings();
316 timingsTotal.timeSortDigi += moduleTime.timeSortDigi;
317 timingsTotal.timeCluster += moduleTime.timeCluster;
318 timingsTotal.timeSortCluster += moduleTime.timeSortCluster;
319 timingsTotal.timeHits += moduleTime.timeHits;
320 }
321
322 // Avoid division by zero if no events present
323 double nEvent = std::max(fNofEvents, 1);
324
325 fTimeTot /= nEvent;
326 fTime1 /= nEvent;
327 fTime2 /= nEvent;
328 fTime3 /= nEvent;
329 fTime4 /= nEvent;
330
331 auto throughput = [](auto bytes, auto timeMs) { return bytes * 1000. / timeMs / double(1ull << 30); };
332
333 if (not fUseGpuReco) {
334 LOG(info) << "NofEvents : " << fNofEvents;
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 ("
338 << setprecision(1) << 100. * fTime2 / fTimeTot << " %)";
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 ("
343 << throughput(fNofDigis * 8, 1000. * fTimeSortDigis) << " GB/s)\n"
344 << " Find Cluster: " << fixed << setprecision(2) << setw(6) << 1000. * fTimeFindClusters << " ms ("
345 << throughput(fNofDigis * sizeof(CbmStsDigi), 1000. * fTimeFindClusters) << " GB/s)\n"
346 << " Sort Cluster: " << fixed << setprecision(2) << setw(6) << 1000. * fTimeSortClusters << " ms ("
347 << throughput(fNofClusters * sizeof(CbmStsCluster), 1000. * fTimeSortClusters) << " GB/s)\n"
348 << " Find Hits : " << fixed << setprecision(2) << setw(6) << 1000. * fTimeFindHits << " ms ("
349 << throughput(fNofClusters * sizeof(CbmStsCluster), 1000. * fTimeFindHits) << " GB/s)";
350 }
351 else {
352 LOG(warn) << "Hitfinder times collected by cbm::algo::Reco";
353 // cbm::algo::StsHitfinderTimes times = fGpuReco.GetHitfinderTimes();
354
355 // double gpuHitfinderTimeTotal = times.timeSortDigi + times.timeCluster + times.timeSortCluster + times.timeHits;
356
357 // double sortDigiThroughput = throughput(fNofDigis * sizeof(CbmStsDigi), times.timeSortDigi);
358 // double findClusterThroughput = throughput(fNofDigis * sizeof(CbmStsDigi), times.timeCluster);
359 // double sortClusterThroughput = throughput(fNofClusters * 8, times.timeSortCluster);
360 // double findHitThroughput = throughput(fNofClusters * 24, times.timeHits);
361
362 // LOG(info) << "Time Reconstruct (GPU) : " << fixed << setprecision(2) << setw(6) << gpuHitfinderTimeTotal << " ms";
363 // LOG(info) << "Time by step:\n"
364 // << " Sort Digi : " << fixed << setprecision(2) << setw(6) << times.timeSortDigi << " ms ("
365 // << sortDigiThroughput << " GB/s)\n"
366 // << " Find Cluster: " << fixed << setprecision(2) << setw(6) << times.timeCluster << " ms ("
367 // << findClusterThroughput << " GB/s)\n"
368 // << " Sort Cluster: " << fixed << setprecision(2) << setw(6) << times.timeSortCluster << " ms ("
369 // << sortClusterThroughput << " GB/s)\n"
370 // << " Find Hits : " << fixed << setprecision(2) << setw(6) << times.timeHits << "ms ("
371 // << findHitThroughput << " GB/s)";
372 }
373 LOG(info) << "=====================================";
374}
375// -------------------------------------------------------------------------
376
377
378// ----- Initialisation ------------------------------------------------
380{
381
382 // --- Something for the screen
383 std::cout << std::endl;
384 LOG(info) << "==========================================================";
385 LOG(info) << GetName() << ": Initialising ";
386
387 // Initialize xpu.
388 // TODO: This call can be relatively expensive.
389 // We need a way to ensure this happens only once at the beginning.
390 if (fUseGpuReco) {
391 setenv("XPU_PROFILE", "1", 1); // Always enable profiling in xpu
392 xpu::initialize();
393 }
394
395 // --- Check IO-Manager
396 FairRootManager* ioman = FairRootManager::Instance();
397 assert(ioman);
398
399 // --- Digi Manager
402
403 // --- In event mode: get input array (CbmEvent)
405 LOG(info) << GetName() << ": Using event-by-event mode";
406 fEvents = dynamic_cast<TClonesArray*>(ioman->GetObject("CbmEvent"));
407 if (nullptr == fEvents) {
408 LOG(warn) << GetName() << ": Event mode selected but no event array found!";
409 return kFATAL;
410 } //? Event branch not present
411 } //? Event mode
412 else
413 LOG(info) << GetName() << ": Using time-based mode";
414
415 // --- Check input array (StsDigis)
416 if (!fDigiManager->IsPresent(ECbmModuleId::kSts)) LOG(fatal) << GetName() << ": No StsDigi branch in input!";
417
418 // --- Register output array
419 fClusters = new TClonesArray("CbmStsCluster", 1);
420 ioman->Register("StsCluster", "Clusters in STS", fClusters, IsOutputBranchPersistent("StsCluster"));
421
422 // --- Register output array
423 fHits = new TClonesArray("CbmStsHit", 1);
424 ioman->Register("StsHit", "Hits in STS", fHits, IsOutputBranchPersistent("StsHit"));
425
426 // --- Simulation settings
427 assert(fParSim);
428 LOG(info) << GetName() << ": Sim settings " << fParSim->ToString();
429
430 // --- Parameters
431 InitParams();
432
433 // --- Initialise STS setup
435 fSetup->Init(nullptr);
436 //fSetup->SetSensorParameters(fParSetSensor);
437
438 // --- Create reconstruction modules
439 UInt_t nModules = CreateModules();
440 LOG(info) << GetName() << ": Created " << nModules << " modules";
441
442 LOG(info) << GetName() << ": Initialisation successful.";
443 LOG(info) << "==========================================================";
444
445 return kSUCCESS;
446}
447// -------------------------------------------------------------------------
448
449
450// ----- Parameter initialisation --------------------------------------
452{
453
454 // --- Module parameters
455 TString sourceModu = "database";
456 assert(fParSetModule);
457 if (fUserParSetModule) {
460 fParSetModule->setChanged();
461 fParSetModule->setInputVersion(-2, 1);
462 sourceModu = "user-defined";
463 }
464 if (fUserParModule) { // global settings override
467 fParSetModule->setChanged();
468 fParSetModule->setInputVersion(-2, 1);
469 sourceModu = "user-defined, global";
470 }
471 LOG(info) << GetName() << ": Module parameters (" << sourceModu << ") " << fParSetModule->ToString();
472
473 // --- Sensor parameters
474 TString sourceSens = "database";
475 assert(fParSetSensor);
476 if (fUserParSetSensor) {
479 fParSetSensor->setChanged();
480 fParSetSensor->setInputVersion(-2, 1);
481 sourceSens = "user-defined";
482 }
483 if (fUserParSensor) { // global settings override
486 fParSetSensor->setChanged();
487 fParSetSensor->setInputVersion(-2, 1);
488 sourceSens = "user-defined, global";
489 }
490 LOG(info) << GetName() << ": Sensor parameters (" << sourceSens << ") " << fParSetSensor->ToString();
491
492 // --- Sensor conditions
493 TString sourceCond = "database";
494 assert(fParSetCond);
495 if (fUserParSetCond) {
498 fParSetCond->setChanged();
499 fParSetCond->setInputVersion(-2, 1);
500 sourceSens = "user-defined";
501 }
502 if (fUserParCond) { // global settings override
505 fParSetCond->setChanged();
506 fParSetCond->setInputVersion(-2, 1);
507 sourceCond = "user-defined, global";
508 }
509 LOG(info) << GetName() << ": Sensor conditions (" << sourceCond << ")" << fParSetCond->ToString();
510}
511// -------------------------------------------------------------------------
512
513// -------------------------------------------------------------------------
515{
516 LOG_IF(warn, useGpu) << "CbmRecoSts: GPU STS reconstruction temporarily disabled! Will use CPU reco instead.";
517 fUseGpuReco = false;
518}
519// -------------------------------------------------------------------------
520
521
522// ----- Calculate the mean Lorentz shift in a sensor ------------------
523std::pair<Double_t, Double_t> CbmRecoSts::LorentzShift(const CbmStsParSensorCond& conditions, Double_t dZ, Double_t bY)
524{
525
526 Double_t vBias = conditions.GetVbias(); // Bias voltage
527 Double_t vFd = conditions.GetVfd(); // Full-depletion voltage
528 Double_t eField = (vBias + vFd) / dZ; // Electric field
529
530 // --- Integrate in 1000 steps over the sensor thickness
531 Int_t nSteps = 1000;
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; // Electric field [V/cm]
537 Double_t muHallE = conditions.GetHallMobility(eField, 0);
538 Double_t muHallH = conditions.GetHallMobility(eField, 1);
539 dxMeanE += muHallE * (dZ - Double_t(j) * deltaZ);
540 dxMeanH += muHallH * Double_t(j) * deltaZ;
541 }
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;
546 // The factor 1.e-4 is because bZ is in T = Vs/m**2, but muHall is in
547 // cm**2/(Vs) and z in cm.
548
549 return {shiftF, shiftB};
550}
551// -------------------------------------------------------------------------
552
553
554// ----- Process one time slice or event -------------------------------
556{
557
558 // --- Reset all modules
559 fTimer.Start();
560 Int_t nDigisIgnored = 0;
561 Int_t nClusters = 0;
562 Int_t nHits = 0;
563
564#ifdef _OPENMP
565#pragma omp parallel for schedule(static)
566#endif
567 for (UInt_t it = 0; it < fModuleIndex.size(); it++) {
568 fModuleIndex[it]->Reset();
569 }
570 fTimer.Stop();
571 Double_t time1 = fTimer.RealTime(); // Time for resetting
572
573 // --- Number of input digis
574 fTimer.Start();
575 Int_t nDigis = (event ? event->GetNofData(ECbmDataType::kStsDigi) : fDigiManager->GetNofDigis(ECbmModuleId::kSts));
576 auto digis = fDigiManager->GetArray<CbmStsDigi>();
577
578 // --- Distribute digis to modules
579 //#pragma omp parallel for schedule(static) if(fParallelism_enabled)
580 for (Int_t iDigi = 0; iDigi < nDigis; iDigi++) {
581 Int_t digiIndex = (event ? event->GetIndex(ECbmDataType::kStsDigi, iDigi) : iDigi);
582 const CbmStsDigi* digi = &digis[digiIndex];
583
584 // Check system ID. There are pulser digis in which will be ignored here.
585 Int_t systemId = CbmAddress::GetSystemId(digi->GetAddress());
586 if (systemId != ToIntegralType(ECbmModuleId::kSts)) {
587 nDigisIgnored++;
588 continue;
589 }
590
591 // Get proper reco module
592 Int_t moduleAddress = CbmStsAddress::GetMotherAddress(digi->GetAddress(), kStsModule);
593 auto it = fModules.find(moduleAddress);
594 if (it == fModules.end()) {
595 LOG(warn) << "Unknown module address: " << CbmStsAddress::ToString(moduleAddress);
596 ;
597 }
598 assert(it != fModules.end());
599 CbmStsRecoModule* module = it->second;
600 assert(module);
601 module->AddDigiToQueue(digi, digiIndex);
602 }
603 fTimer.Stop();
604 Double_t time2 = fTimer.RealTime(); // Time for digi distribution
605
606
607 // --- Execute reconstruction in the modules
608 // Run each step individually. This allows us to meassure the runtime of each step
609 // even when running in parallel
610 TStopwatch timeSubstep;
611 fTimer.Start();
612 timeSubstep.Start();
613#ifdef _OPENMP
614#pragma omp parallel for schedule(static)
615#endif
616 for (UInt_t it = 0; it < fModuleIndex.size(); it++) {
617 assert(fModuleIndex[it]);
618 fModuleIndex[it]->SortDigis();
619 }
620 timeSubstep.Stop();
621 fTimeSortDigis = timeSubstep.RealTime();
622
623 timeSubstep.Start();
624#ifdef _OPENMP
625#pragma omp parallel for schedule(static)
626#endif
627 for (UInt_t it = 0; it < fModuleIndex.size(); it++) {
628 assert(fModuleIndex[it]);
629 fModuleIndex[it]->FindClusters();
630 }
631 timeSubstep.Stop();
632 fTimeFindClusters = timeSubstep.RealTime();
633
634 timeSubstep.Start();
635#ifdef _OPENMP
636#pragma omp parallel for schedule(static)
637#endif
638 for (UInt_t it = 0; it < fModuleIndex.size(); it++) {
639 assert(fModuleIndex[it]);
640 fModuleIndex[it]->SortClusters();
641 }
642 timeSubstep.Stop();
643 fTimeSortClusters = timeSubstep.RealTime();
644
645 timeSubstep.Start();
646#ifdef _OPENMP
647#pragma omp parallel for schedule(static)
648#endif
649 for (UInt_t it = 0; it < fModuleIndex.size(); it++) {
650 assert(fModuleIndex[it]);
651 fModuleIndex[it]->FindHits();
652 }
653 timeSubstep.Stop();
654 fTimeFindHits = timeSubstep.RealTime();
655
656 fTimer.Stop();
657 Double_t time3 = fTimer.RealTime(); // Time for reconstruction
658
659 // --- Collect clusters and hits from modules
660 // Here, the hits (and optionally clusters) are copied to the
661 // TClonesArrays in the ROOT tree. This is surely not the last word
662 // in terms of framework. It thus cannot be considered optimised.
663 // The output shall eventually be tailored to provide the proper
664 // input for further reconstruction (track finding).
665 fTimer.Start();
666 ULong64_t offsetClustersF = 0;
667 ULong64_t offsetClustersB = 0;
668 for (UInt_t it = 0; it < fModuleIndex.size(); it++) {
669
670 const vector<CbmStsCluster>& moduleClustersF = fModuleIndex[it]->GetClustersF();
671
672 offsetClustersF = fClusters->GetEntriesFast();
673 for (auto& cluster : moduleClustersF) {
674 UInt_t index = fClusters->GetEntriesFast();
675 new ((*fClusters)[index]) CbmStsCluster(cluster);
676 if (event) event->AddData(ECbmDataType::kStsCluster, index);
677 nClusters++;
678 } //# front-side clusters in module
679
680 const vector<CbmStsCluster>& moduleClustersB = fModuleIndex[it]->GetClustersB();
681
682 offsetClustersB = fClusters->GetEntriesFast();
683 for (auto& cluster : moduleClustersB) {
684 UInt_t index = fClusters->GetEntriesFast();
685 new ((*fClusters)[index]) CbmStsCluster(cluster);
686 if (event) event->AddData(ECbmDataType::kStsCluster, index);
687 nClusters++;
688 } //# back-side clusters in module
689
690 const vector<CbmStsHit>& moduleHits = fModuleIndex[it]->GetHits();
691 for (auto& hit : moduleHits) {
692 UInt_t index = fHits->GetEntriesFast();
693 CbmStsHit* out = new ((*fHits)[index]) CbmStsHit(hit);
694 out->SetFrontClusterId(out->GetFrontClusterId() + offsetClustersF);
695 out->SetBackClusterId(out->GetBackClusterId() + offsetClustersB);
696 if (event) event->AddData(ECbmDataType::kStsHit, index);
697 nHits++;
698 } //# hits in module
699 }
700 fTimer.Stop();
701 Double_t time4 = fTimer.RealTime(); // Time for data I/O
702
703 // --- Bookkeeping
704 Double_t realTime = time1 + time2 + time3 + time4;
705 fNofDigis += nDigis;
706 fNofDigisUsed += nDigis - nDigisIgnored;
707 fNofDigisIgnored += nDigisIgnored;
708 fNofClusters += nClusters;
709 fNofHits += nHits;
710 fTimeTot += realTime;
711 fTime1 += time1;
712 fTime2 += time2;
713 fTime3 += time3;
714 fTime4 += time4;
715
716 // --- Screen log
717 if (event) {
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;
721 } //? event mode
722 else {
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;
726 }
727}
728// -------------------------------------------------------------------------
729
731{
733 throw std::runtime_error("STS GPU Reco does not yet support event-by-event mode.");
734
735 auto digis = fDigiManager->GetArray<CbmStsDigi>();
736 fGpuReco(digis);
737 auto [nClustersForwarded, nHitsForwarded] = ForwardGpuClusterAndHits();
738
739 fNofDigis = digis.size();
740 fNofDigisUsed = digis.size();
741 fNofClusters = nClustersForwarded;
742 fNofHits = nHitsForwarded;
743}
744
745std::pair<size_t, size_t> CbmRecoSts::ForwardGpuClusterAndHits()
746{
747#if 0
748 size_t nClustersForwarded = 0, nHitsForwarded = 0;
749
750 const cbm::algo::StsHitfinderHost& hfc = fGpuReco.GetHitfinderBuffers();
751 const cbm::algo::StsHitfinderPar& pars = fGpuReco.GetParameters();
752
753 for (int module = 0; module < hfc.nModules; module++) {
754
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];
758
759 nClustersForwarded += nClustersFGpu;
760
761 for (int i = 0; i < nClustersFGpu; i++) {
762 auto& cidx = gpuClusterIdxF[i];
763 auto& clusterGpu = gpuClusterF[cidx.fIdx];
764
765 unsigned int outIdx = fClusters->GetEntriesFast();
766 auto* clusterOut = new ((*fClusters)[outIdx])::CbmStsCluster {};
767
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);
772 }
773
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];
777
778 nClustersForwarded += nClustersBGpu;
779
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();
784 auto* clusterOut = new ((*fClusters)[outIdx])::CbmStsCluster {};
785
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);
790 }
791
792 auto* gpuHits = &hfc.hitsPerModule.h()[module * hfc.maxHitsPerModule];
793 int nHitsGpu = hfc.nHitsPerModule.h()[module];
794
795 nHitsForwarded += nHitsGpu;
796
797 for (int i = 0; i < nHitsGpu; i++) {
798 auto& hitGpu = gpuHits[i];
799
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},
804 hitGpu.fDxy,
805 0,
806 0,
807 double(hitGpu.fTime),
808 hitGpu.fTimeError,
809 hitGpu.fDu,
810 hitGpu.fDv};
811 }
812
813 } // for (int module = 0; module < hfc.nModules; module++)
814
815 return {nClustersForwarded, nHitsForwarded};
816#endif
817 return {0, 0};
818}
819
820
821// ----- Connect parameter container -----------------------------------
823{
824 FairRuntimeDb* db = FairRun::Instance()->GetRuntimeDb();
825 fParSim = dynamic_cast<CbmStsParSim*>(db->getContainer("CbmStsParSim"));
826 fParSetModule = dynamic_cast<CbmStsParSetModule*>(db->getContainer("CbmStsParSetModule"));
827 fParSetSensor = dynamic_cast<CbmStsParSetSensor*>(db->getContainer("CbmStsParSetSensor"));
828 fParSetCond = dynamic_cast<CbmStsParSetSensorCond*>(db->getContainer("CbmStsParSetSensorCond"));
829}
830// -------------------------------------------------------------------------
831
833{
834 LOG(warn) << "DumpNewHits() not implemented yet";
835 // std::ofstream out {"newHits.csv"};
836 // const cbm::algo::StsHitfinderHost& hfc = fGpuReco.GetHitfinderBuffers();
837 // out << "module, x, y, z, deltaX, deltaY, deltaZ, deltaXY, time, timeError, deltaU, deltaV" << std::endl;
838 // for (size_t m = 0; m < fModuleIndex.size(); m++) {
839 // int nHitsGpu = hfc.nHitsPerModule.h()[m];
840 // auto* gpuHits = &hfc.hitsPerModule.h()[m * hfc.maxHitsPerModule];
841 // for (int i = 0; i < nHitsGpu; i++) {
842 // auto& h = gpuHits[i];
843 // out << m << ", " << h.fX << ", " << h.fY << ", " << h.fZ << ", " << h.fDx << ", " << h.fDy << ", " << h.fDz
844 // << ", " << h.fDxy << ", " << h.fTime << ", " << h.fTimeError << ", " << h.fDu << ", " << h.fDv << std::endl;
845 // }
846 // }
847}
848
850{
851 std::ofstream out{"oldHits.csv"};
852
853 out << "module, x, y, z, deltaX, deltaY, deltaZ, deltaXY, time, timeError, deltaU, deltaV" << std::endl;
854
855 for (size_t m = 0; m < fModuleIndex.size(); m++) {
856 const auto& hits = fModuleIndex[m]->GetHits();
857
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;
862 }
863 }
864}
ECbmRecoMode
Reconstruct the full time slice or event-by-event.
Definition CbmDefs.h:162
XPU_D constexpr auto ToIntegralType(T enumerator) -> typename std::underlying_type< T >::type
Definition CbmDefs.h:29
@ kSts
Silicon Tracking System.
ClassImp(CbmRecoSts)
@ kStsModule
static vector< vector< QAHit > > hits
static int32_t GetSystemId(uint32_t address)
Definition CbmAddress.h:47
void SetAddress(int32_t address)
Definition CbmCluster.h:94
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,...
Definition CbmEvent.h:34
Task class for local reconstruction in the STS.
Definition CbmRecoSts.h:54
Long64_t fNofDigisUsed
Total number of used digis.
Definition CbmRecoSts.h:288
Double_t fTime2
Time for distributing data.
Definition CbmRecoSts.h:294
Double_t fTimeCutClustersSig
Time cut for hit finding.
Definition CbmRecoSts.h:282
CbmRecoSts(ECbmRecoMode mode=ECbmRecoMode::Timeslice, Bool_t writeClusters=kFALSE)
Constructor.
CbmStsParSetSensorCond * fParSetCond
Sensor conditions.
Definition CbmRecoSts.h:265
CbmStsParSetSensor * fParSetSensor
Sensor parameters.
Definition CbmRecoSts.h:264
double fTimeFindClusters
Definition CbmRecoSts.h:298
Int_t fNofTs
ROOT timer.
Definition CbmRecoSts.h:304
void DumpNewHits()
Double_t fTimeCutClustersAbs
Time cut for hit finding [ns].
Definition CbmRecoSts.h:283
CbmStsParSetSensor * fUserParSetSensor
Definition CbmRecoSts.h:275
cbm::algo::sts::HitfinderChain fGpuReco
Definition CbmRecoSts.h:323
Double_t fNofDigisRun
Total number of digis processed.
Definition CbmRecoSts.h:306
void ProcessDataGpu()
CbmStsParSim * fParSim
Instance of STS setup.
Definition CbmRecoSts.h:262
void InitParams()
Initialise parameters.
ECbmRecoMode fMode
Time-slice or event-by-event.
Definition CbmRecoSts.h:279
std::map< UInt_t, CbmStsRecoModule * > fModules
Definition CbmRecoSts.h:319
CbmStsSetup * fSetup
Output hit array.
Definition CbmRecoSts.h:261
Double_t fTime1Run
Time for resetting modules.
Definition CbmRecoSts.h:312
CbmStsParSetModule * fUserParSetModule
Definition CbmRecoSts.h:274
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.
Definition CbmRecoSts.h:289
Double_t fNofHitsRun
Total number of clusters produced.
Definition CbmRecoSts.h:310
void SetUseGpuReco(bool useGPU)
std::vector< CbmStsRecoModule * > fModuleIndex
Definition CbmRecoSts.h:320
Int_t fNofEvents
Number of events processed.
Definition CbmRecoSts.h:305
TClonesArray * fClusters
Interface to digi branch.
Definition CbmRecoSts.h:257
double fTimeSortClusters
Definition CbmRecoSts.h:299
Double_t fTime1
Time for resetting modules.
Definition CbmRecoSts.h:293
CbmStsParSensorCond * fUserParCond
Definition CbmRecoSts.h:271
UInt_t CreateModules()
Instantiate reconstruction modules @value Number of modules created.
TClonesArray * fHits
Output cluster array.
Definition CbmRecoSts.h:258
double fTimeSortDigis
Definition CbmRecoSts.h:297
CbmDigiManager * fDigiManager
Input array of events.
Definition CbmRecoSts.h:256
TStopwatch fTimer
Definition CbmRecoSts.h:303
void DumpOldHits()
Double_t fTimeCutDigisSig
Time cut for cluster finding.
Definition CbmRecoSts.h:280
CbmStsParSetModule * fParSetModule
Module parameters.
Definition CbmRecoSts.h:263
Double_t fTime4Run
Time for output results.
Definition CbmRecoSts.h:315
Double_t fTime3
Time for reconstruction.
Definition CbmRecoSts.h:295
Double_t fNofDigisUsedRun
Total number of used digis.
Definition CbmRecoSts.h:307
CbmStsParSensor * fUserParSensor
Definition CbmRecoSts.h:270
Long64_t fNofHits
Total number of clusters produced.
Definition CbmRecoSts.h:291
Double_t fTimeTot
Total execution time.
Definition CbmRecoSts.h:292
bool fUseGpuReco
Definition CbmRecoSts.h:322
Long64_t fNofDigis
Total number of digis processed.
Definition CbmRecoSts.h:287
Double_t fTime2Run
Time for distributing data.
Definition CbmRecoSts.h:313
Double_t fTimeCutDigisAbs
Time cut for cluster finding [ns].
Definition CbmRecoSts.h:281
Double_t fTimeRun
Total execution time.
Definition CbmRecoSts.h:311
Long64_t fNofClusters
Total number of clusters produced.
Definition CbmRecoSts.h:290
virtual ~CbmRecoSts()
Destructor
virtual InitStatus Init()
Initialisation.
Double_t fTime4
Time for output results.
Definition CbmRecoSts.h:296
virtual void SetParContainers()
Define the needed parameter containers.
Double_t fNofClustersRun
Total number of clusters produced.
Definition CbmRecoSts.h:309
std::pair< size_t, size_t > ForwardGpuClusterAndHits()
TClonesArray * fEvents
Definition CbmRecoSts.h:255
CbmStsParSetSensorCond * fUserParSetCond
Definition CbmRecoSts.h:276
CbmStsParModule * fUserParModule
Definition CbmRecoSts.h:269
virtual void Exec(Option_t *opt)
Task execution.
double fTimeFindHits
Definition CbmRecoSts.h:300
virtual void Finish()
End-of-run action.
Double_t fTime3Run
Time for reconstruction.
Definition CbmRecoSts.h:314
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.
Definition CbmStsDigi.h:40
XPU_D int32_t GetAddress() const
Definition CbmStsDigi.h:74
Class representing an element of the STS setup.
Int_t GetAddress() const
TGeoPhysicalNode * GetPnode() const
Int_t GetNofDaughters() const
CbmStsElement * GetDaughter(Int_t index) const
data class for a reconstructed 3-d hit in the STS
Definition CbmStsHit.h:35
int32_t GetFrontClusterId() const
Definition CbmStsHit.h:105
void SetFrontClusterId(int32_t index)
Set the index of the frontside cluster To keep track of the input during matching.
Definition CbmStsHit.h:111
void SetBackClusterId(int32_t index)
Set the index of the backside cluster To keep track of the input during matching.
Definition CbmStsHit.h:117
int32_t GetBackClusterId() const
Definition CbmStsHit.h:65
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 &params)
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 &params)
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.
Definition CbmStsSetup.h:72
static CbmStsSetup * Instance()
Int_t GetNofModules() const
Definition CbmStsSetup.h:86
Data class with information on a STS local track.
const HitfinderChainPars & GetParameters() const
void SetParameters(const HitfinderChainPars &parameters)
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.