Skip to content

Commit ce995a1

Browse files
committed
Reproducible simulation on the track level
This commit introduces the possibly to have binary reproducible simulation on the individual track level, in the sense that: "If we change simulation of track A, it will never influence the simulation of track B unless B is a child of A." This is very useful for systematic optimization studies (for instance studying the effect of geometry tracking limits on the physics). Before this commit, a change in tracking limit would have influenced the evolution of the overall simulation leading to large statistical fluctuations in the hits. Such fluctuations make it difficult to judge the usefulness of a parameter change or require a large production study. We use here the idea of seeding the RNG for each track -- based on a unique hash derived from its properties and independent of the history of the track. (The hash function is needs review). By default the option is disabled. It can be enabled via `o2sim --configKeyValues = "SimCutParams.trackSeed=1` For the moment, this only works with Geant3. The commit also provides an updated macro to statistically analyse hits. This macro can be used to detect if a simulation parameter change has an impact on physics.
1 parent 857e1db commit ce995a1

8 files changed

Lines changed: 362 additions & 221 deletions

File tree

Common/SimConfig/include/SimConfig/SimCutParams.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@ namespace conf
2222
// (mostly used in O2MCApplication stepping)
2323
struct SimCutParams : public o2::conf::ConfigurableParamHelper<SimCutParams> {
2424
bool stepFiltering = true; // if we activate the step filtering in O2BaseMCApplication
25+
bool trackSeed = false; // per track seeding for track-reproducible mode
2526

2627
double maxRTracking = 1E20; // max R tracking cut in cm (in the VMC sense) -- applied in addition to cutting in the stepping function
2728
double maxAbsZTracking = 1E20; // max |Z| tracking cut in cm (in the VMC sense) -- applied in addition to cutting in the stepping function
29+
double ZmaxA = 1E20; // max Z tracking cut on A side in cm -- applied in the stepping function
30+
double ZmaxC = 1E20; // max Z tracking cut on C side in cm -- applied in the stepping function
2831

2932
O2ParamDef(SimCutParams, "SimCutParams");
3033
};

DataFormats/simulation/src/Stack.cxx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "DetectorsBase/Detector.h"
1717
#include "DetectorsCommonDataFormats/DetID.h"
1818
#include "SimulationDataFormat/MCTrack.h"
19+
#include "SimConfig/SimCutParams.h"
1920

2021
#include "FairDetector.h" // for FairDetector
2122
#include "FairLogger.h" // for FairLogger
@@ -245,6 +246,28 @@ void Stack::notifyFinishPrimary()
245246
}
246247
}
247248

249+
// calculates a hash based on particle properties
250+
// hash may serve as seed for this track
251+
ULong_t getHash(TParticle const& p)
252+
{
253+
auto asLong = [](double x) {
254+
return (ULong_t) * (reinterpret_cast<ULong_t*>(&x));
255+
};
256+
257+
ULong_t hash;
258+
o2::MCTrackT<double> track(p);
259+
260+
hash = asLong(track.GetStartVertexCoordinatesX());
261+
hash ^= asLong(track.GetStartVertexCoordinatesY());
262+
hash ^= asLong(track.GetStartVertexCoordinatesZ());
263+
hash ^= asLong(track.GetStartVertexCoordinatesT());
264+
hash ^= asLong(track.GetStartVertexMomentumX());
265+
hash ^= asLong(track.GetStartVertexMomentumY());
266+
hash ^= asLong(track.GetStartVertexMomentumZ());
267+
hash += (ULong_t)track.GetPdgCode();
268+
return hash;
269+
}
270+
248271
TParticle* Stack::PopNextTrack(Int_t& iTrack)
249272
{
250273
// This functions is mainly used by Geant3?
@@ -276,6 +299,16 @@ TParticle* Stack::PopNextTrack(Int_t& iTrack)
276299
mIndexOfCurrentTrack = mCurrentParticle.GetStatusCode();
277300
iTrack = mIndexOfCurrentTrack;
278301

302+
if (o2::conf::SimCutParams::Instance().trackSeed) {
303+
auto hash = getHash(mCurrentParticle);
304+
// LOG(INFO) << "SEEDING NEW TRACK USING HASH" << hash;
305+
// init seed per track
306+
gRandom->SetSeed(hash);
307+
308+
// NOTE: THE BETTER PLACE WOULD BE IN PRETRACK HOOK BUT THIS DOES NOT SEEM TO WORK
309+
// WORKS ONLY WITH G3 SINCE G4 DOES NOT CALL THIS FUNCTION
310+
}
311+
279312
// LOG(INFO) << "transporting ID " << mIndexOfCurrentTrack << "\n";
280313
return &mCurrentParticle;
281314
}

Detectors/Passive/src/Cave.cxx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "DetectorsBase/Detector.h"
2626
#include "DetectorsPassive/Cave.h"
2727
#include "SimConfig/SimConfig.h"
28+
#include "SimConfig/SimCutParams.h"
2829
#include <TRandom.h>
2930
#include "FairLogger.h"
3031
#include "TGeoManager.h"
@@ -105,14 +106,17 @@ void Cave::BeginPrimary()
105106
{
106107
static int primcounter = 0;
107108

108-
auto& conf = o2::conf::SimConfig::Instance();
109-
auto chunks = conf.getInternalChunkSize();
110-
if (chunks != -1) {
111-
if (primcounter % chunks == 0) {
112-
static int counter = 1;
113-
auto seed = counter + 10;
114-
gRandom->SetSeed(seed);
115-
counter++;
109+
// only do it, if not in pure trackSeeding mode
110+
if (!o2::conf::SimCutParams::Instance().trackSeed) {
111+
auto& conf = o2::conf::SimConfig::Instance();
112+
auto chunks = conf.getInternalChunkSize();
113+
if (chunks != -1) {
114+
if (primcounter % chunks == 0) {
115+
static int counter = 1;
116+
auto seed = counter + 10;
117+
gRandom->SetSeed(seed);
118+
counter++;
119+
}
116120
}
117121
}
118122
primcounter++;

Steer/include/Steer/O2MCApplication.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class O2MCApplication : public O2MCApplicationBase
6161
det->EndOfEvent();
6262
}
6363
fStack->Reset();
64+
LOG(INFO) << "This event/chunk did " << mStepCounter << " steps";
6465
}
6566

6667
/** Define actions at the end of run */

Steer/include/Steer/O2MCApplicationBase.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,17 @@ class O2MCApplicationBase : public FairMCApplication
4242
~O2MCApplicationBase() override = default;
4343

4444
void Stepping() override;
45+
void PreTrack() override;
46+
void BeginEvent() override;
47+
void FinishEvent() override;
4548

4649
// specific implementation of our hard geometry limits
4750
double TrackingRmax() const override { return mCutParams.maxRTracking; }
4851
double TrackingZmax() const override { return mCutParams.maxAbsZTracking; }
4952

5053
protected:
5154
o2::conf::SimCutParams const& mCutParams; // reference to parameter system
55+
unsigned long long mStepCounter{ 0 };
5256

5357
ClassDefOverride(O2MCApplicationBase, 1)
5458
};

Steer/src/O2MCApplication.cxx

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,46 @@ void TypedVectorAttach(const char* name, FairMQChannel& channel, FairMQParts& pa
4545

4646
void O2MCApplicationBase::Stepping()
4747
{
48+
mStepCounter++;
49+
if (mCutParams.stepFiltering) {
50+
// we can kill tracks here based on our
51+
// custom detector specificities
52+
53+
float x, y, z;
54+
fMC->TrackPosition(x, y, z);
55+
56+
if (z > mCutParams.ZmaxA) {
57+
fMC->StopTrack();
58+
return;
59+
}
60+
if (-z > mCutParams.ZmaxC) {
61+
fMC->StopTrack();
62+
return;
63+
}
64+
}
65+
4866
// dispatch first to stepping function in FairRoot
4967
FairMCApplication::Stepping();
68+
}
5069

51-
// now the right place to put our specific step/filtering criteria:
70+
void O2MCApplicationBase::PreTrack()
71+
{
72+
// dispatch first to function in FairRoot
73+
FairMCApplication::PreTrack();
74+
}
75+
76+
void O2MCApplicationBase::FinishEvent()
77+
{
78+
// dispatch first to function in FairRoot
79+
FairMCApplication::FinishEvent();
80+
LOG(INFO) << "This event/chunk did " << mStepCounter << " steps";
81+
}
82+
83+
void O2MCApplicationBase::BeginEvent()
84+
{
85+
// dispatch first to function in FairRoot
86+
FairMCApplication::BeginEvent();
87+
mStepCounter = 0;
5288
}
5389

5490
void O2MCApplication::initLate()

0 commit comments

Comments
 (0)