CbmRoot
Loading...
Searching...
No Matches
CbmStsDigitize.cxx
Go to the documentation of this file.
1/* Copyright (C) 2014-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Volker Friese [committer] */
4
9
10// Include class header
11#include "CbmStsDigitize.h"
12
13// Includes from C++
14#include <cassert>
15#include <cstring>
16#include <fstream>
17#include <iomanip>
18#include <iostream>
19#include <sstream>
20#include <tuple>
21
22// Includes from ROOT
23#include "TClonesArray.h"
24#include "TGeoBBox.h"
25#include "TGeoMatrix.h"
26#include "TGeoPhysicalNode.h"
27#include "TGeoVolume.h"
28
29#include <TMCProcess.h>
30
31// Includes from FairRoot
32#include "FairEventHeader.h"
33#include "FairField.h"
34#include "FairLink.h"
35#include "FairMCEventHeader.h"
36#include "FairMCPoint.h"
37#include "FairRunAna.h"
38#include "FairRunSim.h"
39#include "FairRuntimeDb.h"
40
41#include <Logger.h>
42
43// Includes from CbmRoot
44#include "CbmMCTrack.h"
45#include "CbmStsDigi.h"
46#include "CbmStsPoint.h"
47
48// Includes from STS
49#include "CbmStsModule.h"
50#include "CbmStsParAsic.h"
51#include "CbmStsParModule.h"
52#include "CbmStsParSensor.h"
53#include "CbmStsParSensorCond.h"
54#include "CbmStsParSetModule.h"
55#include "CbmStsParSetSensor.h"
57#include "CbmStsParSim.h"
58#include "CbmStsPhysics.h"
59#include "CbmStsSensor.h"
60#include "CbmStsSetup.h"
62
63using std::fixed;
64using std::left;
65using std::right;
66using std::setprecision;
67using std::setw;
68using std::string;
69using std::stringstream;
70
71using namespace CbmSts;
72
73
74// ----- Standard constructor ------------------------------------------
76 : CbmDigitize<CbmStsDigi>("StsDigitize")
77 , fIsInitialised(kFALSE)
78 ,
79 //fModuleParameterMap(),
80 fSetup(nullptr)
81 , fPoints(nullptr)
82 , fTracks(nullptr)
83 , fTimer()
84 , fSensorDinact(0.12)
85 , fSensorPitch(0.0058)
86 , fSensorStereoF(0.)
87 , fSensorStereoB(7.5)
91 , fTimePointLast(-1.)
92 , fTimeDigiFirst(-1.)
93 , fTimeDigiLast(-1.)
94 , fAsicParamsFileName(nullptr) // Initialize to an empty string
95{
98}
99// -------------------------------------------------------------------------
100
101
102// ----- Destructor ----------------------------------------------------
104// -------------------------------------------------------------------------
105
106
107// ----- Content of analogue buffers -----------------------------------
109{
110 Int_t nSignals = 0;
111 Int_t nSigModule;
112 Double_t t1Module;
113 Double_t t2Module;
114
115 for (auto& entry : fModules) {
116 entry.second->BufferStatus(nSigModule, t1Module, t2Module);
117 nSignals += nSigModule;
118 } //# modules
119
120 return nSignals;
121}
122// -------------------------------------------------------------------------
123
124
125// ----- Print the status of the analogue buffers ----------------------
127{
128
129 Int_t nSignals = 0;
130 Double_t t1 = -1;
131 Double_t t2 = -1.;
132
133 Int_t nSigModule;
134 Double_t t1Module;
135 Double_t t2Module;
136
137 for (auto& entry : fModules) {
138 entry.second->BufferStatus(nSigModule, t1Module, t2Module);
139 if (nSigModule) {
140 nSignals += nSigModule;
141 t1 = t1 < 0. ? t1Module : TMath::Min(t1, t1Module);
142 t2 = TMath::Max(t2, t2Module);
143 } //? signals in module buffer?
144 } //# modules in setup
145
146 std::stringstream ss;
147 ss << nSignals << (nSignals == 1 ? " signal " : " signals ") << "in analogue buffers";
148 if (nSignals) ss << " ( from " << fixed << setprecision(3) << t1 << " ns to " << t2 << " ns )";
149 return ss.str();
150}
151// -------------------------------------------------------------------------
152
153
154// ----- Create a digi object ------------------------------------------
155void CbmStsDigitize::CreateDigi(Int_t address, UShort_t channel, Long64_t time, UShort_t adc, const CbmMatch& match)
156{
157 assert(time >= 0);
158
159 // No action if the channel is marked inactive
160 if (!IsChannelActiveSts(address, channel)) return;
161
162 // Update times of first and last digi
163 fTimeDigiFirst = fNofDigis ? TMath::Min(fTimeDigiFirst, Double_t(time)) : time;
164 fTimeDigiLast = TMath::Max(fTimeDigiLast, Double_t(time));
165
166 // Create digi and (if required) match and send them to DAQ
167 // Digi time is set later, when creating the timestamp
168 CbmStsDigi* digi = new CbmStsDigi(address, channel, 0, adc);
169 if (fCreateMatches) {
170 CbmMatch* digiMatch = new CbmMatch(match);
171 SendData(time, digi, digiMatch);
172 }
173 else
174 SendData(time, digi);
175 fNofDigis++;
176}
177// -------------------------------------------------------------------------
178
179
180// ----- Task execution ------------------------------------------------
181void CbmStsDigitize::Exec(Option_t* /*opt*/)
182{
183
184 // --- Start timer and reset counters
185 fTimer.Start();
187
188 // --- For debug: status of analogue buffers
189 if (fair::Logger::Logging(fair::Severity::debug)) {
190 std::cout << std::endl;
191 LOG(debug) << GetName() << ": " << BufferStatus();
192 }
193
194 // --- Store previous event time. Get current event time.
195 Double_t eventTimePrevious = fCurrentEventTime;
196 GetEventInfo();
197
198 // --- Generate noise from previous to current event time
199 if (fParSim->Noise()) {
200 Int_t nNoise = 0;
201 Double_t tNoiseStart = fNofEvents ? eventTimePrevious : fRunStartTime;
202 Double_t tNoiseEnd = fCurrentEventTime;
203 for (auto& entry : fModules)
204 nNoise += entry.second->GenerateNoise(tNoiseStart, tNoiseEnd);
205 fNofNoiseTot += Double_t(nNoise);
206 LOG(info) << "+ " << setw(20) << GetName() << ": Generated " << nNoise << " noise signals from t = " << tNoiseStart
207 << " ns to " << tNoiseEnd << " ns";
208 }
209
210 // --- Analogue response: Process the input array of StsPoints
212 LOG(debug) << GetName() << ": " << fNofSignalsF + fNofSignalsB << " signals generated ( " << fNofSignalsF << " / "
213 << fNofSignalsB << " )";
214 // --- For debug: status of analogue buffers
215 if (fair::Logger::Logging(fair::Severity::debug)) {
216 LOG(debug) << GetName() << ": " << BufferStatus();
217 }
218
219 // --- Digital response: Process buffers of all modules. In event mode, this
220 // --- is triggered after each event. In time-based mode, it can be triggered at regular
221 // --- time intervals in order to limit the content of the buffers for runtime reason.
222 if (fEventMode) {
223 ProcessAnalogBuffers(-1.); // digitize everything
224 }
225 else {
227 ProcessAnalogBuffers(fCurrentEventTime); // digitize up to current event time minus deadtime
229 }
230 }
231
232 // --- Check status of analogue module buffers
233 if (fair::Logger::Logging(fair::Severity::debug)) {
234 LOG(debug) << GetName() << ": " << BufferStatus();
235 }
236
237 // --- Event log
238 LOG(info) << left << setw(15) << GetName() << "[" << fixed << setprecision(3) << fTimer.RealTime() << " s]"
239 << " Points: processed " << fNofPointsProc << ", ignored " << fNofPointsIgno
240 << ", signals: " << fNofSignalsF << " / " << fNofSignalsB << ", digis: " << fNofDigis;
241
242 // --- Counters
243 fTimer.Stop();
244 fNofEvents++;
250 fTimeTot += fTimer.RealTime();
251}
252// -------------------------------------------------------------------------
253
254
255// ----- Finish run ---------------------------------------------------
257{
258
259 // --- Start timer and reset counters
260 fTimer.Start();
262
263 // --- In event-by-event mode, the analogue buffers should be empty.
264 if (fEventMode) {
265 if (BufferSize()) {
266 LOG(info) << fName << BufferStatus();
267 LOG(fatal) << fName << ": Non-empty analogue buffers at end of event "
268 << " in event-by-event mode!";
269 } //? buffers not empty
270 } //? event-by-event mode
271
272 // --- In time-based mode: process the remaining signals in the buffers
273 else {
274 std::cout << std::endl;
275 LOG(info) << GetName() << ": Finish run";
276 LOG(info) << GetName() << ": " << BufferStatus();
277 LOG(info) << GetName() << ": Processing analogue buffers";
278
279 // --- Process buffers of all modules
280 for (auto& entry : fModules)
281 entry.second->ProcessAnalogBuffer(-1.);
282
283 // --- Screen output
284 stringstream ss;
285 ss << GetName() << ": " << fNofDigis << (fNofDigis == 1 ? " digi " : " digis ") << "created and sent to DAQ ";
286 if (fNofDigis)
287 ss << "( from " << fixed << setprecision(3) << fTimeDigiFirst << " ns to " << fTimeDigiLast << " ns )";
288 LOG(info) << ss.str();
289 LOG(info) << GetName() << ": " << BufferStatus();
290 }
291
292 fTimer.Stop();
298 fTimeTot += fTimer.RealTime();
299
300 std::cout << std::endl;
301 LOG(info) << "=====================================";
302 LOG(info) << GetName() << ": Run summary";
303 LOG(info) << "Events processed : " << fNofEvents;
304 LOG(info) << "Points processed / evt : " << fixed << setprecision(1) << fNofPointsProcTot / Double_t(fNofEvents);
305 LOG(info) << "Points ignored / evt : " << fixed << setprecision(1) << fNofPointsIgnoTot / Double_t(fNofEvents);
306 LOG(info) << "Signals / event : " << fNofSignalsFTot / Double_t(fNofEvents) << " / "
307 << fNofSignalsBTot / Double_t(fNofEvents);
308 LOG(info) << "StsDigi / event : " << fNofDigisTot / Double_t(fNofEvents);
309 LOG(info) << "Digis per point : " << setprecision(6) << fNofDigisTot / fNofPointsProcTot;
310 LOG(info) << "Digis per signal : " << fNofDigisTot / (fNofSignalsFTot + fNofSignalsBTot);
311 LOG(info) << "Noise digis / event : " << fNofNoiseTot / Double_t(fNofEvents);
312 LOG(info) << "Noise fraction : " << fNofNoiseTot / fNofDigisTot;
313 LOG(info) << "Real time per event : " << fTimeTot / Double_t(fNofEvents) << " s";
314 LOG(info) << "=====================================";
315}
316// -------------------------------------------------------------------------
317
318
319// ----- Get parameter container from runtime DB -----------------------
321{
322 assert(FairRunAna::Instance());
323 FairRuntimeDb* rtdb = FairRunAna::Instance()->GetRuntimeDb();
324 fParSim = static_cast<CbmStsParSim*>(rtdb->getContainer("CbmStsParSim"));
325 fParSetModule = static_cast<CbmStsParSetModule*>(rtdb->getContainer("CbmStsParSetModule"));
326 fParSetSensor = static_cast<CbmStsParSetSensor*>(rtdb->getContainer("CbmStsParSetSensor"));
327 fParSetCond = static_cast<CbmStsParSetSensorCond*>(rtdb->getContainer("CbmStsParSetSensorCond"));
328}
329// -------------------------------------------------------------------------
330
331
332// ----- Initialisation -----------------------------------------------
334{
335
336 // Screen output
337 std::cout << std::endl;
338 LOG(info) << "==========================================================";
339 LOG(info) << GetName() << ": Initialisation \n\n";
340
341 // Initialise the STS setup interface from TGeoManager
343 fSetup->Init();
344
345 // --- Instantiate StsPhysics
347
348 // --- Initialise parameters
349 InitParams();
350
351 // --- Read list of inactive channels
352 if (!fInactiveChannelFileName.IsNull()) {
353 LOG(info) << GetName() << ": Reading inactive channels from " << fInactiveChannelFileName;
354 auto result = ReadInactiveChannels();
355 if (!result.second) {
356 LOG(error) << GetName() << ": Error in reading from file! Task will be inactive.";
357 return kFATAL;
358 }
359 LOG(info) << GetName() << ": " << std::get<0>(result) << " lines read from file";
360 }
361 size_t nChanInactive = 0;
362 for (auto& entry : fInactiveChannelsSts)
363 nChanInactive += entry.second.size();
364 LOG(info) << GetName() << ": " << nChanInactive << " channels set inactive";
365
366 // Instantiate modules
367 UInt_t nModules = InitModules();
368 LOG(info) << GetName() << ": Created " << nModules << " modules";
369
370 // Instantiate sensors
371 UInt_t nSensors = InitSensors();
372 LOG(info) << GetName() << ": Created " << nSensors << " sensors";
373
374 // --- Get FairRootManager instance
375 FairRootManager* ioman = FairRootManager::Instance();
376 assert(ioman);
377
378 // --- Get input array (CbmStsPoint)
379 fPoints = (TClonesArray*) ioman->GetObject("StsPoint");
380 assert(fPoints);
381
382 // --- Get input array (CbmMCTrack)
383 fTracks = (TClonesArray*) ioman->GetObject("MCTrack");
384 assert(fTracks);
385
386 // --- Register the output branches
388
389 // --- Screen output
390 LOG(info) << GetName() << ": Initialisation successful";
391 LOG(info) << "==========================================================";
392 std::cout << std::endl;
393
394 // Set static initialisation flag
395 fIsInitialised = kTRUE;
396
397 return kSUCCESS;
398}
399// -------------------------------------------------------------------------
400
401
402// ----- Instantiation of modules --------------------------------------
404{
405
406 UInt_t nModules = 0;
407 fModules.clear();
408
409 for (Int_t iModule = 0; iModule < fSetup->GetNofModules(); iModule++) {
410 CbmStsElement* geoModule = fSetup->GetModule(iModule);
411 assert(geoModule);
412 UInt_t address = geoModule->GetAddress();
413 auto& modulePar = fParSetModule->GetParModule(address);
414 CbmStsSimModule* module = new CbmStsSimModule(geoModule, &modulePar, this);
415 auto result = fModules.insert({address, module});
416 assert(result.second); // If false, module was already in map
417 nModules++;
418 } //# modules in setup
419
420 assert(nModules == fModules.size());
421 return nModules;
422}
423// -------------------------------------------------------------------------
424
425
426// ----- Initialise parameters -----------------------------------------
428{
429
430 // --- The parameter containers are completely initialised here.
431 // --- Any contents possibly obtained from the runtimeDb are ignored
432 // --- and overwritten.
433
434 // --- Simulation settings
435 assert(fParSim);
436 assert(fUserParSim);
437 *fParSim = *fUserParSim; // adapt user settings
438 fParSim->SetEventMode(fEventMode); // from CbmDigitizeBase
439 fParSim->SetGenerateNoise(fProduceNoise); // from CbmDigitizeBase
440 /* fParSim->SetProcesses(fUserParSim->ELossModel(),
441 fUserParSim->LorentzShift(),
442 fUserParSim->Diffusion(),
443 fUserParSim->CrossTalk());
444 */
445 if (fEventMode) fParSim->SetGenerateNoise(kFALSE);
446 fParSim->setChanged();
447 fParSim->setInputVersion(-2, 1);
448 LOG(info) << "--- Settings: " << fParSim->ToString();
449
450 // --- Module parameters (global for the time being)
451 assert(fParSetModule);
452 fParSetModule->clear();
453 assert(fUserParModule);
454 assert(fUserParAsic);
455 fUserParModule->SetAllAsics(*fUserParAsic);
456
457 for (Int_t iModule = 0; iModule < fSetup->GetNofModules(); iModule++) {
458 UInt_t address = fSetup->GetModule(iModule)->GetAddress();
459 uint32_t numAsics = fUserParModule->GetNofAsics();
460
461 for (uint32_t iAsic = 0; iAsic < numAsics; iAsic++) {
462
463 Int_t side = (iAsic < (numAsics / 2)) ? 0 : 1;
464
465 auto specificKey = std::make_tuple(address, side, iAsic);
466 auto globalKey = std::make_tuple(address, side, -1);
467
468 const CbmStsParAsic* asicParam = nullptr;
469
470 // Set parameters for specific ASIC index (a case when ASIC index is not -1)
471 if (auto specificIndex_it = fModuleAsicParams.find(specificKey); specificIndex_it != fModuleAsicParams.end()) {
472 asicParam = specificIndex_it->second.get();
473 }
474 // Set Asic parameters only if no specific ASIC index parameter exists (a case when ASIC index is -1)
475 else if (auto globalIndex_it = fModuleAsicParams.find(globalKey); globalIndex_it != fModuleAsicParams.end()) {
476 asicParam = globalIndex_it->second.get();
477 }
478 // otherwise fallback to default parameters to set for all other ASICs index
479 else {
480 asicParam = fUserParAsic;
481 }
482
483 fUserParModule->SetAsic(iAsic, *asicParam);
484 }
485
486 fParSetModule->SetParModule(address, *fUserParModule);
487 }
488 UInt_t deactivated = 0;
489 if (fUserFracDeadChan > 0.) {
490 deactivated = fParSetModule->DeactivateRandomChannels(fUserFracDeadChan);
491 }
492 fParSetModule->setChanged();
493 fParSetModule->setInputVersion(-2, 1);
494 LOG(info) << "--- Using global ASIC parameters: \n " << fUserParAsic->ToString();
495 LOG(info) << "--- Module parameters: " << fParSetModule->ToString();
496 LOG(info) << "--- Deactive channels: " << deactivated << " " << fUserFracDeadChan;
497
498 // --- Sensor parameters
499 // TODO: The code above is highly unsatisfactory. A better implementation
500 // would use data sheets with the actual sensor design parameters.
501 assert(fParSetSensor);
502 fParSetSensor->clear();
503 assert(fUserParSensor);
504 for (Int_t iSensor = 0; iSensor < fSetup->GetNofSensors(); iSensor++) {
505 CbmStsSensor* sensor = fSetup->GetSensor(iSensor);
506 UInt_t address = sensor->GetAddress();
507 TGeoBBox* box = dynamic_cast<TGeoBBox*>(sensor->GetPnode()->GetShape());
508 assert(box);
509 Double_t lX = 2. * box->GetDX();
510 Double_t lY = 2. * box->GetDY();
511 Double_t lZ = 2. * box->GetDZ();
512 Double_t dX = lX - 2. * fUserDinactive;
513 Double_t dY = lY - 2. * fUserDinactive;
514
515 // In general, the number of strips is given by the active size in x
516 // divided by the strip pitch.
517 Double_t pitchF = fUserParSensor->GetPar(6);
518 Double_t pitchB = fUserParSensor->GetPar(7);
519 Double_t nStripsF = dX / pitchF;
520 Double_t nStripsB = dX / pitchB;
521
522 // The stereo sensors with 6.2092 cm width have 1024 strips with 58 mum.
523 if (fUserParSensor->GetClass() == CbmStsSensorClass::kDssdStereo && TMath::Abs(lX - 6.2092) < 0.0001
524 && TMath::Abs(pitchF - 0.0058) < 0.0001) {
525 nStripsF = 1024.;
526 nStripsB = 1024.;
527 }
528
529 // Same for sensors with 6.2000 cm width
530 if (fUserParSensor->GetClass() == CbmStsSensorClass::kDssdStereo && TMath::Abs(lX - 6.2) < 0.0001
531 && TMath::Abs(pitchF - 0.0058) < 0.0001) {
532 nStripsF = 1024.;
533 nStripsB = 1024.;
534 }
535
536 // Create a sensor parameter object and add it to the container
537 CbmStsParSensor par(fUserParSensor->GetClass());
538 par.SetPar(0, lX); // Extension in x
539 par.SetPar(1, lY); // Extension in y
540 par.SetPar(2, lZ); // Extension in z
541 par.SetPar(3, dY); // Active size in y
542 par.SetPar(4, nStripsF); // Number of strips front side
543 par.SetPar(5, nStripsB); // Number of strips back side
544 for (UInt_t parIndex = 6; parIndex < 10; parIndex++) {
545 par.SetPar(parIndex, fUserParSensor->GetPar(parIndex));
546 } //# parameters 6 - 9 (pitches and stereo angles) set by user or default
547 fParSetSensor->SetParSensor(address, par);
548
549 } //# sensors in setup
550 LOG(info) << "--- Sensor parameters: " << fParSetSensor->ToString();
551 fParSetSensor->setChanged();
552 fParSetSensor->setInputVersion(-2, 1);
553
554 // --- Sensor conditions
555 assert(fParSetCond);
556 fParSetCond->clear();
557 fParSetCond->SetGlobalPar(*fUserParCond);
558 LOG(info) << "--- Sensor conditions: " << fParSetCond->ToString();
559 fParSetCond->setChanged();
560 fParSetCond->setInputVersion(-2, 1);
561}
562// -------------------------------------------------------------------------
563
564
565// ----- Instantiation of sensors --------------------------------------
567{
568
569 UInt_t nSensors = 0;
570 fSensors.clear();
571
573 for (Int_t iSensor = 0; iSensor < fSetup->GetNofSensors(); iSensor++) {
574
575 // --- Sensor and module elements in setup
576 CbmStsElement* geoSensor = fSetup->GetSensor(iSensor);
577 assert(geoSensor); // Valid geo sensor
578 UInt_t sensAddress = geoSensor->GetAddress();
579 CbmStsElement* geoModule = geoSensor->GetMother();
580 assert(geoModule); // Valid geo mother module
581 UInt_t moduAddress = geoModule->GetAddress();
582
583 // --- Simulation module
584 auto moduIt = fModules.find(moduAddress);
585 assert(moduIt != fModules.end());
586 assert(moduIt->second); // Valid sim module
587
588 // --- Sensor parameters
589 const CbmStsParSensor& sensorPar = fParSetSensor->GetParSensor(sensAddress);
590
591 // --- Create simulation sensor accordoing to its class
592 auto result = fSensors.insert(std::make_pair(sensAddress, fSensorFactory->CreateSensor(sensorPar)));
593 assert(result.second); // If false, sensor was already in map
594 auto& sensor = result.first->second;
595 assert(sensor); // Valid sensor pointer
596
597 // Assign setup element and module
598 sensor->SetElement(geoSensor);
599 sensor->SetModule(moduIt->second);
600
601 // Assign simulation settings
602 sensor->SetSimSettings(fParSim);
603
604 // Set sensor conditions
605 assert(fParSetCond);
606 const CbmStsParSensorCond& cond = fParSetCond->GetParSensor(sensAddress);
607 sensor->SetConditions(&cond);
608
609 // Get the magnetic field in the sensor centre
610 Double_t bx = 0.;
611 Double_t by = 0.;
612 Double_t bz = 0.;
613 if (FairRun::Instance()->GetField()) {
614 Double_t local[3] = {0., 0., 0.}; // sensor centre in local C.S.
615 Double_t global[3]; // sensor centre in global C.S.
616 geoSensor->GetPnode()->GetMatrix()->LocalToMaster(local, global);
617 Double_t field[3] = {0., 0., 0.}; // magnetic field components
618 FairRun::Instance()->GetField()->Field(global, field);
619 bx = field[0] / 10.; // kG->T
620 by = field[1] / 10.; // kG->T
621 bz = field[2] / 10.; // kG->T
622 } //? field present
623 sensor->SetField(bx, by, bz);
624
625 // Initialise sensor
626 assert(sensor->Init());
627
628 nSensors++;
629 } //# sensors in setup
630
631 assert(nSensors == fSensors.size());
632 return nSensors;
633}
634// -------------------------------------------------------------------------
635
636
637// ----- Initialisation of setup --------------------------------------
639{
640
641 // Initialise the STS setup interface from TGeoManager
643 fSetup->Init();
644
645 // Set parameters to modules and sensor
646 fSetup->SetModuleParameters(fParSetModule);
647 fSetup->SetSensorParameters(fParSetSensor);
648 fSetup->SetSensorConditions(fParSetCond);
649
650 // Individual configuration
651 //fSetup->SetModuleParameterMap(fModuleParameterMap);
652}
653// -------------------------------------------------------------------------
654
655
656// ----- Check for channel being active --------------------------------
657bool CbmStsDigitize::IsChannelActiveSts(Int_t address, UShort_t channel)
658{
659 auto it = fInactiveChannelsSts.find(address);
660 if (it == fInactiveChannelsSts.end()) return true;
661 if (it->second.count(channel)) return false;
662 return true;
663}
664// -------------------------------------------------------------------------
665
666
667// ----- Process the analogue buffers of all modules -------------------
668void CbmStsDigitize::ProcessAnalogBuffers(Double_t readoutTime)
669{
670 LOG(info) << "StsDigitize: Process analog buffers at " << readoutTime;
671 // --- Process analogue buffers of all modules
672 for (auto& it : fModules)
673 it.second->ProcessAnalogBuffer(readoutTime);
674}
675// -------------------------------------------------------------------------
676
677
678// ----- Process points from MC event ---------------------------------
680{
681
682 // --- Loop over all StsPoints and execute the ProcessPoint method
683 assert(fPoints);
684 for (Int_t iPoint = 0; iPoint < fPoints->GetEntriesFast(); iPoint++) {
685 const CbmStsPoint* point = (const CbmStsPoint*) fPoints->At(iPoint);
686
687 // --- Ignore points from secondaries if the respective flag is set
688 if (fParSim->OnlyPrimaries()) {
689 Int_t iTrack = point->GetTrackID();
690 if (iTrack >= 0) { // MC track is present
691 CbmMCTrack* track = (CbmMCTrack*) fTracks->At(iTrack);
692 assert(track);
693 if (track->GetGeantProcessId() != kPPrimary) {
695 continue;
696 }
697 } //? MC track present
698 } //? discard secondaries
699
700 // --- Ignore points with unphysical time
701 // Such instances were observed using Geant4 in the fairsoft jun19 version.
702 // The cut at 1 ms from the event start is somehow arbitrary, but should suit the purpose.
703 // If not cut here, the time range for the StsDigi (2^31 ns) might be exceeded in
704 // flexible time slices or in event-by-event simulation.
705 if (point->GetTime() > 1.e6) {
707 continue;
708 }
709
710 // --- Process the StsPoint
711 CbmLink link(1., iPoint, fCurrentMCEntry, fCurrentInput);
712 ProcessPoint(point, fCurrentEventTime, link);
714 } //# StsPoints
715}
716// -------------------------------------------------------------------------
717
718
719// ----- Process a StsPoint ---------------------------------------------
720void CbmStsDigitize::ProcessPoint(const CbmStsPoint* point, Double_t eventTime, const CbmLink& link)
721{
722
723 // --- Get the sensor the point is in
724 UInt_t address = static_cast<UInt_t>(point->GetDetectorID());
725 assert(fSensors.count(address));
726 auto& sensor = fSensors.find(address)->second;
727 assert(sensor);
728 Int_t status = sensor->ProcessPoint(point, eventTime, link);
729
730 // --- Statistics
731 Int_t nSignalsF = status / 1000;
732 Int_t nSignalsB = status - 1000 * nSignalsF;
733 LOG(debug2) << GetName() << ": Produced signals: " << nSignalsF + nSignalsB << " ( " << nSignalsF << " / "
734 << nSignalsB << " )";
735 fNofSignalsF += nSignalsF;
736 fNofSignalsB += nSignalsB;
737}
738// -------------------------------------------------------------------------
739
740
741// ----- Read list of inactive channels from file -----------------------
743{
744
745 if (fInactiveChannelFileName.IsNull()) return std::make_pair(0, true);
746
747 FILE* channelFile = fopen(fInactiveChannelFileName.Data(), "r");
748 if (channelFile == nullptr) return std::make_pair(0, false);
749
750 size_t nLines = 0;
751 uint32_t address = 0;
752 uint16_t channel = 0;
753 while (fscanf(channelFile, "%u %hu", &address, &channel) == 2) {
754 fInactiveChannelsSts[address].insert(channel);
755 nLines++;
756 }
757 bool success = feof(channelFile);
758
759 fclose(channelFile);
760 return std::make_pair(nLines, success);
761}
762// -------------------------------------------------------------------------
763
764
765// ----- Function to read the External Ascii file for Asic Parameters Setting to get read -----
767{
768
769 // Set filename and open the file
770 std::ifstream file(fileName);
771
772 if (!file.is_open()) {
773 LOG(error) << "Error: Could not open file " << fileName;
774 return false;
775 }
776
777 std::string line;
778 bool File_Load_Success = false;
779 std::string Error_Message;
780
781 while (std::getline(file, line)) {
782 // Skip empty or comment lines
783 if (line.empty() || line[0] == '#') continue;
784
785 // Parse the ASIC parameters line
786 std::istringstream iss(line);
787 std::string moduleAddressStr;
788 UInt_t moduleAddress;
789 Int_t side, AsicIdx;
790 UShort_t nAsicChannels, nAdc;
791 Double_t dynRange, threshold, timeResol, deadTime, noiseRms, znr;
792
793 // Read the module address as a string to check for hex format
794 if (!(iss >> moduleAddressStr >> side >> AsicIdx >> nAsicChannels >> nAdc >> dynRange >> threshold >> timeResol
795 >> deadTime >> noiseRms >> znr)) {
796 Error_Message = "Error parsing line: " + line;
797 LOG(error) << Error_Message;
798 break;
799 }
800
801 // Check if the module address is in hexadecimal format or decimal
802 try {
803 int base = (moduleAddressStr.compare(0, 2, "0x") == 0 || moduleAddressStr.compare(0, 2, "0X") == 0) ? 16 : 10;
804 moduleAddress = std::stoul(moduleAddressStr, nullptr, base);
805 }
806 catch (const std::exception& e) {
807 LOG(error) << "Invalid module address format: " << moduleAddressStr << " (" << e.what() << ")";
808 continue;
809 }
810
811 auto key = std::make_tuple(moduleAddress, side, AsicIdx);
812
813 fModuleAsicParams.emplace(key, std::make_unique<CbmStsParAsic>(nAsicChannels, nAdc, dynRange, threshold, timeResol,
814 deadTime, noiseRms, znr));
815
816 File_Load_Success = true;
817 }
818
819 file.close();
820 return File_Load_Success;
821}
822
823
824// ----- Private method ReInit -----------------------------------------
826{
827
829
830 return kERROR;
831}
832// -------------------------------------------------------------------------
833
834
835// ----- Reset event counters ------------------------------------------
837{
839 fNofPointsProc = 0;
840 fNofPointsIgno = 0;
841 fNofSignalsF = 0;
842 fNofSignalsB = 0;
843 fNofDigis = 0;
844}
845// -------------------------------------------------------------------------
846
847
848// ----- Global default values for parameters --------------------------
850{
851
852 // The global default values cannot be directly stored in the parameter
853 // containers, since these are not yet initialised from the database.
854
855 // --- Protect against setting after initialisation
856 assert(!fIsInitialised);
857
858 // --- Simulation settings
859 if (fUserParSim) delete fUserParSim;
861 Bool_t eventMode = kFALSE;
862 CbmStsELoss eLossModel = CbmStsELoss::kUrban;
863 Bool_t lorentzShift = kTRUE;
864 Bool_t diffusion = kTRUE;
865 Bool_t crossTalk = kTRUE;
866 Bool_t generateNoise = kTRUE;
867 fUserParSim->SetEventMode(eventMode);
868 fUserParSim->SetProcesses(eLossModel, lorentzShift, diffusion, crossTalk);
869 fUserParSim->SetGenerateNoise(generateNoise);
870 // Note that the run mode and the generation of noise are centrally set
871 // through the base class CbmDigitizeBase, such that the settings here
872 // will be overwritten later (in Init).
873
874 // --- Module parameters
875 if (fUserParModule) delete fUserParModule;
876 UInt_t nChannels = 2048; // Number of module readout channels
877 UInt_t nAsicChannels = 128; // Number of readout channels per ASIC
878 fUserParModule = new CbmStsParModule(nChannels, nAsicChannels);
879
880 // --- ASIC parameters
881 if (fUserParAsic) delete fUserParAsic;
882 UShort_t nAdc = 31; // Number of ADC channels (5 bit)
883 Double_t dynRange = 75000.; // Dynamic range [e]
884 Double_t threshold = 4000.; // Threshold [e]
885 Double_t timeResol = 5.; // Time resolution [ns]
886 Double_t deadTime = 200.; // Channel dead time [ns]
887 Double_t noiseRms = 1000.; // RMS of noise [e]
888 Double_t znr = 3.5368e-3; // Zero-crossing noise rate [1/ns]
889 fUserParAsic = new CbmStsParAsic(nAsicChannels, nAdc, dynRange, threshold, timeResol, deadTime, noiseRms, znr);
890 // --- Sensor parameters
891 // --- Here, only the default pitch and stereo angles are defined. The
892 // --- other parameters are extracted from the geometry.
893 if (fUserParSensor) delete fUserParSensor;
895 fUserParSensor = new CbmStsParSensor(sClass);
896 Double_t pitchF = 0.0058; // Strip pitch front side
897 Double_t pitchB = 0.0058; // Strip pitch back side
898 Double_t stereoF = 0.; // Stereo angle front side
899 Double_t stereoB = 7.5; // Stereo angle back side [deg]
900 fUserParSensor->SetPar(6, pitchF);
901 fUserParSensor->SetPar(7, pitchB);
902 fUserParSensor->SetPar(8, stereoF);
903 fUserParSensor->SetPar(9, stereoB);
904 fUserDinactive = 0.12; // Size of inactive sensor border [cm]
905
906 // --- Sensor conditions
907 if (fUserParCond) delete fUserParCond;
908 Double_t vFd = 70.; // Full-depletion voltage
909 Double_t vBias = 140.; // Bias voltage
910 Double_t temperature = 268.; // Temperature
911 Double_t cCoupling = 17.5; // Coupling capacitance [pF]
912 Double_t cInterstrip = 1.; // Inter-strip capacitance
913 fUserParCond = new CbmStsParSensorCond(vFd, vBias, temperature, cCoupling, cInterstrip);
914}
915// -------------------------------------------------------------------------
916
917
918// ----- Set the global module parameters ------------------------------
919void CbmStsDigitize::SetGlobalAsicParams(UShort_t nChannels, UShort_t nAdc, Double_t dynRange, Double_t threshold,
920 Double_t timeResolution, Double_t deadTime, Double_t noise,
921 Double_t zeroNoiseRate)
922{
923 assert(!fIsInitialised);
924 assert(nAdc > 0);
925 if (fUserParAsic) delete fUserParAsic;
927 new CbmStsParAsic(nChannels, nAdc, dynRange, threshold, timeResolution, deadTime, noise, zeroNoiseRate);
928}
929// -------------------------------------------------------------------------
930
931
932// ----- Set the global module parameters ------------------------------
933void CbmStsDigitize::SetGlobalModuleParams(UInt_t nChannels, UInt_t nAsicChannels)
934{
935 assert(!fIsInitialised);
936
937 if (fUserParModule) delete fUserParModule;
938 fUserParModule = new CbmStsParModule(nChannels, nAsicChannels);
939}
940// -------------------------------------------------------------------------
941
942
943// ----- Set the global sensor conditions ------------------------------
944void CbmStsDigitize::SetGlobalSensorConditions(Double_t vFd, Double_t vBias, Double_t temperature, Double_t cCoupling,
945 Double_t cInterstrip)
946{
947 assert(!fIsInitialised);
948
949 if (fUserParCond) delete fUserParCond;
950 fUserParCond = new CbmStsParSensorCond(vFd, vBias, temperature, cCoupling, cInterstrip);
951}
952// -------------------------------------------------------------------------
953
954
955// ----- Set sensor parameter file -------------------------------------
957{
958
959 assert(!fIsInitialised);
960 fModuleParameterFile = fileName;
961}
962// -------------------------------------------------------------------------
963
964
965// ----- Set physical processes for the analogue response ---------------
966void CbmStsDigitize::SetProcesses(CbmStsELoss eLossModel, Bool_t useLorentzShift, Bool_t useDiffusion,
967 Bool_t useCrossTalk)
968{
969 if (fIsInitialised) {
970 LOG(error) << GetName() << ": physics processes must be set before "
971 << "initialisation! Statement will have no effect.";
972 return;
973 }
974
975 fUserParSim->SetProcesses(eLossModel, useLorentzShift, useDiffusion, useCrossTalk);
976}
977// -------------------------------------------------------------------------
978
979
980// ----- Set sensor condition file -------------------------------------
982{
983
984 if (fIsInitialised) {
985 LOG(fatal) << GetName() << ": sensor conditions must be set before initialisation!";
986 return;
987 }
988 fSensorConditionFile = fileName;
989}
990// -------------------------------------------------------------------------
991
992
993// ----- Set sensor parameter file -------------------------------------
995{
996
997 if (fIsInitialised) {
998 LOG(fatal) << GetName() << ": sensor parameters must be set before initialisation!";
999 return;
1000 }
1001 fSensorParameterFile = fileName;
1002}
1003// -------------------------------------------------------------------------
1004
1005
1006// ----- Usage of primary tracks only ----------------------------------
1007void CbmStsDigitize::UseOnlyPrimaries(Bool_t flag) { fUserParSim->SetOnlyPrimaries(flag); }
1008// -------------------------------------------------------------------------
1009
ClassImp(CbmConverterManager)
CbmStsSensorClass
Sensor classes.
Definition CbmStsDefs.h:68
CbmStsELoss
Energy loss model used in simulation.
Definition CbmStsDefs.h:49
int Int_t
bool Bool_t
void SendData(Double_t time, CbmStsDigi *digi, CbmMatch *match=nullptr)
uint32_t GetGeantProcessId() const
Definition CbmMCTrack.h:66
Data class for a single-channel message in the STS.
Definition CbmStsDigi.h:40
Task class for simulating the detector response of the STS.
TString fSensorConditionFile
File with sensor conditions.
const char * fAsicParamsFileName
Double_t fTimeTot
Total execution time.
void SetGlobalDefaults()
Set global default parameters.
UInt_t InitModules()
Instantiate modules.
virtual void Exec(Option_t *opt)
Bool_t fIsInitialised
kTRUE if Init() was called
Double_t fNofPointsIgnoTot
Total number of ignored points.
virtual ~CbmStsDigitize()
CbmStsParModule * fUserParModule
User defined, global.
Double_t fSensorDinact
Size of inactive border [cm].
Double_t fSensorStereoB
Stereo angle back side [degrees].
void SetSensorParameterFile(const char *fileName)
Set the file name with sensor parameters.
TClonesArray * fTracks
Input array of CbmMCTrack.
void SetSensorConditionFile(const char *fileName)
Set the file name with sensor conditions.
Int_t fNofSignalsF
Number of signals on front side.
TClonesArray * fPoints
Sensor factory.
Double_t fReadoutInterval
Interval for analog buffer readout [ns].
Double_t fSensorPitch
Strip pitch [cm].
CbmStsParAsic * fUserParAsic
User defined, global.
std::map< UInt_t, std::unique_ptr< CbmStsSimSensor > > fSensors
virtual InitStatus Init()
Double_t fNofSignalsFTot
Number of signals on front side.
void SetGlobalModuleParams(UInt_t nChannels, UInt_t nAsicChannels)
Set the global module parameters.
Int_t fNofPointsProc
Number of processed points.
Double_t fTimeDigiFirst
Time of first digi sent to DAQ.
CbmStsSimSensorFactory * fSensorFactory
STS setup interface.
TStopwatch fTimer
ROOT timer.
void ProcessAnalogBuffers(Double_t readoutTime)
Int_t fNofDigis
Number of created digis in Exec.
Int_t BufferSize() const
Number of signals in the analogue buffers @value nSignals Sum of number of signals in all modules.
TString fModuleParameterFile
File with module parameters.
Double_t fNofDigisTot
Total number of digis created.
Double_t fSensorStereoF
Stereo angle front side [degrees].
Double_t fTimeLastReadout
Time of last readout of analog buffers.
CbmStsParSensor * fUserParSensor
User defined, global.
TString fSensorParameterFile
File with sensor parameters.
CbmStsParSim * fParSim
Simulation settings.
std::map< std::tuple< UInt_t, Int_t, Int_t >, std::unique_ptr< CbmStsParAsic > > fModuleAsicParams
void SetGlobalAsicParams(UShort_t nChannels, UShort_t nAdc, Double_t dynRange, Double_t threshold, Double_t timeResolution, Double_t deadTime, Double_t noise, Double_t zeroNoiseRate)
Set individual module parameters.
void UseOnlyPrimaries(Bool_t flag=kTRUE)
Discard processing of secondary tracks.
virtual InitStatus ReInit()
Double_t fNofPointsProcTot
Total number of processed points.
CbmStsParSetModule * fParSetModule
Module parameter.
std::map< UInt_t, CbmStsSimModule * > fModules
virtual void Finish()
CbmStsSetup * fSetup
Double_t fNofNoiseTot
Total number of noise digis.
void ProcessPoint(const CbmStsPoint *point, Double_t eventTime, const CbmLink &link)
CbmStsParSim * fUserParSim
Settings for simulation.
CbmStsParSetSensorCond * fParSetCond
Sensor conditions.
bool IsChannelActiveSts(Int_t address, UShort_t channel)
Test if the channel of a digi object is set active.
void CreateDigi(Int_t address, UShort_t channel, Long64_t time, UShort_t adc, const CbmMatch &match)
std::pair< size_t, bool > ReadInactiveChannels()
Read the list of inactive channels from file.
std::string BufferStatus() const
Status of the analogue buffers.
void SetProcesses(CbmStsELoss eLossModel, Bool_t useLorentzShift=kTRUE, Bool_t useDiffusion=kTRUE, Bool_t useCrossTalk=kTRUE)
Double_t fUserFracDeadChan
Fraction of inactive ASIC channels.
void InitParams()
Initialise the parameters.
std::map< Int_t, std::set< UShort_t > > fInactiveChannelsSts
Int_t fNofEvents
Total number of processed events.
void SetGlobalSensorConditions(Double_t vDep, Double_t vBias, Double_t temperature, Double_t cCoupling, Double_t cInterstrip)
Set the global sensor conditions.
void SetModuleParameterFile(const char *fileName)
Set the file name with module parameters.
CbmStsParSensorCond * fUserParCond
User defined, global.
Int_t fNofPointsIgno
Number of ignored points.
Double_t fTimePointLast
Time of last processed StsPoint.
Int_t fNofSignalsB
Number of signals on back side.
Double_t fNofSignalsBTot
Number of signals on back side.
UInt_t InitSensors()
Instantiate sensors.
Double_t fUserDinactive
Size of inactive sensor border [cm].
void ResetCounters()
Reset event counters.
CbmStsParSetSensor * fParSetSensor
Sensor parameters.
bool SetAsicParamsFromFile(const char *filename)
Set ASIC parameters from ASCII file.
virtual void SetParContainers()
Inherited from FairTask.
Double_t fTimeDigiLast
Time of last digi sent to DAQ.
Class representing an element of the STS setup.
CbmStsElement * GetMother() const
Int_t GetAddress() const
TGeoPhysicalNode * GetPnode() const
Parameters of the STS readout ASIC.
Parameters for one STS module.
Parameters for operating conditions of a STS sensor.
Constructional parameters of a STS sensor.
void SetPar(UInt_t index, Float_t value)
Set a parameter.
Parameters container for CbmStsParModule.
Parameters container for CbmStsParSensorCond.
Parameters container for CbmStsParSensor.
Settings for STS simulation (digitizer)
static CbmStsPhysics * Instance()
Accessor to singleton instance.
Class representing an instance of a sensor in the CBM-STS.
static CbmStsSetup * Instance()
Class for the simulation of a readout unit in the CBM-STS.