3030#include " TPCCalibration/CorrMapParam.h"
3131
3232#include < fairlogger/Logger.h>
33+ #include < TRandom3.h>
3334
3435ClassImp (o2::tpc::Digitizer);
3536
@@ -39,13 +40,68 @@ Digitizer::~Digitizer() = default;
3940
4041Digitizer::Digitizer () = default;
4142
43+ namespace
44+ {
45+ // splitmix64 finaliser, to derive well separated seeds from the base seed
46+ ULong64_t mixSeed (ULong64_t x)
47+ {
48+ x += 0x9e3779b97f4a7c15ULL ;
49+ x = (x ^ (x >> 30 )) * 0xbf58476d1ce4e5b9ULL ;
50+ x = (x ^ (x >> 27 )) * 0x94d049bb133111ebULL ;
51+ return x ^ (x >> 31 );
52+ }
53+
54+ // TRandom3 takes 32 bits of the seed and treats 0 as a request for a random seed
55+ UInt_t toTRandom3Seed (ULong64_t x)
56+ {
57+ const UInt_t seed = static_cast <UInt_t>(x ^ (x >> 32 ));
58+ return seed ? seed : 1 ;
59+ }
60+ } // namespace
61+
62+ ElectronTransport& Digitizer::electronTransport ()
63+ {
64+ return mElectronTransport ? *mElectronTransport : ElectronTransport::instance ();
65+ }
66+
67+ GEMAmplification& Digitizer::gemAmplification ()
68+ {
69+ return mGEMAmplification ? *mGEMAmplification : GEMAmplification::instance ();
70+ }
71+
72+ SAMPAProcessing& Digitizer::sampaProcessing ()
73+ {
74+ return mSAMPAProcessing ? *mSAMPAProcessing : SAMPAProcessing::instance ();
75+ }
76+
77+ void Digitizer::setUseSectorSeeding (ULong64_t seed)
78+ {
79+ mUseSectorSeeding = true ;
80+ mSeed = seed;
81+ }
82+
4283void Digitizer::init ()
4384{
44- auto & gemAmplification = GEMAmplification::instance ();
85+ if (mUseSectorSeeding ) {
86+ if (!mGEMAmplification ) {
87+ // the rings are filled once, in the construction order of the singletons
88+ TRandom3 rng (toTRandom3Seed (mixSeed (mSeed )));
89+ mGEMAmplification = std::make_unique<GEMAmplification>(&rng);
90+ mElectronTransport = std::make_unique<ElectronTransport>(&rng);
91+ mSAMPAProcessing = std::make_unique<SAMPAProcessing>(&rng);
92+ mDigitContainer .setSAMPAProcessing (mSAMPAProcessing .get ());
93+ }
94+ const ULong64_t sectorSeed = mixSeed (mSeed ^ mixSeed (static_cast <ULong64_t>(mSector ) + 1 ));
95+ TRandom3 rng (toTRandom3Seed (mixSeed (sectorSeed ^ mixSeed (mSeedingTimeframe ))));
96+ mGEMAmplification ->setRandomRingPositions (rng);
97+ mElectronTransport ->setRandomRingPositions (rng);
98+ mSAMPAProcessing ->setRandomRingPositions (rng);
99+ }
100+ auto & gemAmplification = this ->gemAmplification ();
45101 gemAmplification.updateParameters ();
46- auto & electronTransport = ElectronTransport::instance ();
102+ auto & electronTransport = this -> electronTransport ();
47103 electronTransport.updateParameters (mVDrift );
48- auto & sampaProcessing = SAMPAProcessing::instance ();
104+ auto & sampaProcessing = this -> sampaProcessing ();
49105 // the calibration update may reload FEE parameters from file, so SAMPAProcessing picks up its pointers afterwards
50106 mDigitContainer .updateCalibrations ();
51107 sampaProcessing.updateParameters (mVDrift );
@@ -59,9 +115,9 @@ void Digitizer::process(const std::vector<o2::tpc::HitGroup>& hits,
59115 auto & eleParam = ParameterElectronics::Instance ();
60116 auto & gemParam = ParameterGEM::Instance ();
61117
62- auto & gemAmplification = GEMAmplification::instance ();
63- auto & electronTransport = ElectronTransport::instance ();
64- auto & sampaProcessing = SAMPAProcessing::instance ();
118+ auto & gemAmplification = this -> gemAmplification ();
119+ auto & electronTransport = this -> electronTransport ();
120+ auto & sampaProcessing = this -> sampaProcessing ();
65121
66122 const int nShapedPoints = eleParam.NShapedPoints ;
67123 const auto amplificationMode = gemParam.AmplMode ;
@@ -171,7 +227,7 @@ void Digitizer::flush(std::vector<o2::tpc::Digit>& digits,
171227 std::vector<o2::tpc::CommonMode>& commonModeOutput,
172228 bool finalFlush)
173229{
174- SAMPAProcessing& sampaProcessing = SAMPAProcessing::instance ();
230+ SAMPAProcessing& sampaProcessing = this -> sampaProcessing ();
175231 mDigitContainer .fillOutputContainer (digits, labels, commonModeOutput, mSector , sampaProcessing.getTimeBinFromTime (mEventTime - mOutputDigitTimeOffset ), mIsContinuous , finalFlush);
176232 // flushing debug output to file
177233 if (((finalFlush && mIsContinuous ) || (!mIsContinuous )) && mSpaceCharge ) {
@@ -232,7 +288,7 @@ void Digitizer::setStartTime(double time)
232288 // this is setting the first timebin index for the digit container
233289 // note that negative times w.r.t start of timeframe/data-taking == mOutputDigitTimeOffset
234290 // will yield the 0-th bin (due to casting logic in sampaProcessing)
235- SAMPAProcessing& sampaProcessing = SAMPAProcessing::instance ();
291+ SAMPAProcessing& sampaProcessing = this -> sampaProcessing ();
236292 sampaProcessing.updateParameters (mVDrift );
237293 const auto timediff = time - mOutputDigitTimeOffset ;
238294 const auto starttimebin = sampaProcessing.getTimeBinFromTime (timediff);
0 commit comments