Skip to content

Commit 5893629

Browse files
authored
User hook (JITable) for track references during stepping (AliceO2Group#10085)
This commit implements a generic and customizable mechanism to define and execute a callback during MC stepping. The purpose of the callback is to create TrackReferences for certain conditions, but can be used for other purposes (monitoring etc). The callback just takes the instance to TVirtualMC The default implementation creates a TrackReference on "IsStop" whenever the current track already left a TrackReference previously. The feature needs to be switched on via configurable Parameter `SimCutParams.stepTrackRefHook=1` Furthermore, the user can provide own callback implementations via a macro file "MyHook.C". The implementation should follow the following pattern: ``` o2::steer::O2MCApplicationBase::TrackRefFcn trackRefHook() { return [](TVirtualMC const* vmc) { auto stack = (o2::data::Stack*)vmc->GetStack(); if (vmc->IsTrackStop() && stack->currentTrackLeftTrackRef()) { // we add a stopping TrackRef when the current track already // registered previous TrackRefs stack->addTrackReference(o2::TrackReference(*vmc, 0)); } }; } ``` MyHook.C will be activated with `SimCutParams.mCutParams.stepTrackRefHookFile=PATHTO/MyHook.C`
1 parent 9dc769e commit 5893629

10 files changed

Lines changed: 100 additions & 5 deletions

File tree

Common/SimConfig/include/SimConfig/SimParams.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ namespace conf
2323
// (mostly used in O2MCApplication stepping)
2424
struct SimCutParams : public o2::conf::ConfigurableParamHelper<SimCutParams> {
2525
bool stepFiltering = true; // if we activate the step filtering in O2BaseMCApplication
26+
bool stepTrackRefHook = false; // if we create track references during generic stepping
27+
std::string stepTrackRefHookFile = "${O2_ROOT}/share/Detectors/gconfig/StandardSteppingTrackRefHook.macro"; // the standard code holding the TrackRef callback
28+
2629
bool trackSeed = false; // per track seeding for track-reproducible mode
2730

2831
double maxRTracking = 1E20; // max R tracking cut in cm (in the VMC sense) -- applied in addition to cutting in the stepping function

Common/Utils/include/CommonUtils/FileSystemUtils.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ std::vector<std::string> listFiles(std::string const& searchpattern);
3232
// create path if absent, account for eventual concurrent creation
3333
void createDirectoriesIfAbsent(std::string const& path);
3434

35+
// A function to expand a string containing shell variables
36+
// to a string in which these vars have been substituted.
37+
// Motivation:: filesystem::exists() does not do this by default
38+
// and I couldn't find information on this. Potentially there is an
39+
// existing solution.
40+
std::string expandShellVarsInFileName(std::string const& input);
41+
3542
} // namespace o2::utils
3643

3744
#endif //O2_FILEITERATOR_H

Common/Utils/src/FileSystemUtils.cxx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,36 @@ void createDirectoriesIfAbsent(std::string const& path)
6161
throw std::runtime_error(fmt::format("Failed to create {} directory", path));
6262
}
6363
}
64+
// A function to expand string containing shell variables
65+
// to a string in which these vars have been substituted.
66+
// Motivation:: filesystem::exists() does not do this by default
67+
// and I couldn't find information on this. Potentially there is an
68+
// existing solution.
69+
std::string expandShellVarsInFileName(std::string const& input)
70+
{
71+
std::regex e("\\$\\{?[a-zA-Z0-9_]*\\}?");
72+
std::regex e3("[a-zA-Z0-9_]+");
73+
std::string finalstr;
74+
std::sregex_iterator iter;
75+
auto words_end = std::sregex_iterator(); // the end iterator (default)
76+
auto words_begin = std::sregex_iterator(input.begin(), input.end(), e);
77+
std::string tail;
78+
for (auto i = words_begin; i != words_end; ++i) {
79+
std::smatch match = *i;
80+
// remove ${ and }
81+
std::smatch m;
82+
std::string s(match.str());
83+
84+
if (std::regex_search(s, m, e3)) {
85+
auto envlookup = getenv(m[0].str().c_str());
86+
if (envlookup) {
87+
finalstr += match.prefix().str() + std::string(envlookup);
88+
tail = match.suffix().str();
89+
}
90+
}
91+
}
92+
finalstr += tail;
93+
return finalstr;
94+
}
6495

6596
} // namespace o2::utils

DataFormats/simulation/include/SimulationDataFormat/ParticleStatus.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ enum ParticleStatus { kKeep = BIT(14),
2020
kToBeDone = BIT(16),
2121
kPrimary = BIT(17),
2222
kTransport = BIT(18),
23-
kInhibited = BIT(19) };
23+
kInhibited = BIT(19),
24+
kHasHits = BIT(20),
25+
kHasTrackRefs = BIT(21) };
2426

2527
#endif

DataFormats/simulation/include/SimulationDataFormat/Stack.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ class Stack : public FairGenericStack
127127
// the const cast is necessary ... the interface should have been `const TParticle* GetCurrentParticle() const`
128128
return const_cast<TParticle*>(&mCurrentParticle);
129129
}
130+
130131
/// Get the number of the current track
131132
/// Declared in TVirtualMCStack
132133
Int_t GetCurrentTrackNumber() const override { return mIndexOfCurrentTrack; }
@@ -227,6 +228,12 @@ class Stack : public FairGenericStack
227228
/// update values in the current event header
228229
void updateEventStats();
229230

231+
/// returns if current track left a hit
232+
bool currentTrackLeftHit() const { return mCurrentParticle.TestBit(ParticleStatus::kHasHits); }
233+
234+
/// returns if current track left a TrackReference
235+
bool currentTrackLeftTrackRef() const { return mCurrentParticle.TestBit(ParticleStatus::kHasTrackRefs); }
236+
230237
typedef std::function<bool(const TParticle& p, const std::vector<TParticle>& particles)> TransportFcn;
231238

232239
private:
@@ -248,7 +255,7 @@ class Stack : public FairGenericStack
248255
// (mainly for the PopPrimaryParticleInterface
249256
std::vector<TParticle> mPrimaryParticles;
250257

251-
/// vector of reducded tracks written to the output
258+
/// vector of reduced/pruned tracks written to the output
252259
std::vector<o2::MCTrack>* mTracks;
253260

254261
/// STL map from particle index to persistent track index
@@ -325,6 +332,7 @@ inline void Stack::addTrackReference(const o2::TrackReference& ref)
325332
auto& part = mParticles[iTrack];
326333
part.setStore(true);
327334
}
335+
mCurrentParticle.SetBit(ParticleStatus::kHasTrackRefs, 1); // mark that this particle has track refs
328336
mTrackRefs->push_back(ref);
329337
}
330338

DataFormats/simulation/src/Stack.cxx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,13 +646,15 @@ void Stack::addHit(int iDet)
646646
auto& part = mParticles[iTrack];
647647
part.setHit(iDet);
648648
}
649+
mCurrentParticle.SetBit(ParticleStatus::kHasHits, 1);
649650
mHitCounter++;
650651
}
651652
void Stack::addHit(int iDet, Int_t iTrack)
652653
{
653654
mHitCounter++;
654655
auto& part = mParticles[iTrack];
655656
part.setHit(iDet);
657+
mCurrentParticle.SetBit(ParticleStatus::kHasHits, 1);
656658
}
657659

658660
Int_t Stack::GetCurrentParentTrackNumber() const

Detectors/gconfig/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,4 @@ o2_add_test_root_macro(g3Config.C
6262

6363

6464
o2_data_file(COPY data DESTINATION Detectors/gconfig/)
65-
install(FILES src/FlukaRuntimeConfig.macro DESTINATION share/Detectors/gconfig/)
65+
install(FILES src/StandardSteppingTrackRefHook.macro src/FlukaRuntimeConfig.macro DESTINATION share/Detectors/gconfig/)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// A default implementation of a hook called during
2+
// MC stepping, with the aim to produce track references in the
3+
// generic step function.
4+
5+
o2::steer::O2MCApplicationBase::TrackRefFcn trackRefHook() {
6+
return [](TVirtualMC const* vmc) {
7+
auto stack = (o2::data::Stack*)vmc->GetStack();
8+
if (vmc->IsTrackStop() && stack->currentTrackLeftTrackRef()) {
9+
// we add a stopping TrackRef when the current track already
10+
// registered previous TrackRefs
11+
stack->addTrackReference(o2::TrackReference(*vmc, 0));
12+
}
13+
};
14+
}

Steer/include/Steer/O2MCApplicationBase.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ namespace steer
3535
class O2MCApplicationBase : public FairMCApplication
3636
{
3737
public:
38-
O2MCApplicationBase() : FairMCApplication(), mCutParams(o2::conf::SimCutParams::Instance()) {}
38+
O2MCApplicationBase() : FairMCApplication(), mCutParams(o2::conf::SimCutParams::Instance()) { initTrackRefHook(); }
3939
O2MCApplicationBase(const char* name, const char* title, TObjArray* ModList, const char* MatName) : FairMCApplication(name, title, ModList, MatName), mCutParams(o2::conf::SimCutParams::Instance())
4040
{
41+
initTrackRefHook();
4142
}
4243

4344
~O2MCApplicationBase() override = default;
@@ -55,6 +56,8 @@ class O2MCApplicationBase : public FairMCApplication
5556
double TrackingRmax() const override { return mCutParams.maxRTracking; }
5657
double TrackingZmax() const override { return mCutParams.maxAbsZTracking; }
5758

59+
typedef std::function<void(TVirtualMC const*)> TrackRefFcn;
60+
5861
protected:
5962
o2::conf::SimCutParams const& mCutParams; // reference to parameter system
6063
unsigned long long mStepCounter{0};
@@ -64,6 +67,8 @@ class O2MCApplicationBase : public FairMCApplication
6467

6568
/// some common parts of finishEvent
6669
void finishEventCommon();
70+
TrackRefFcn mTrackRefFcn; // a function hook that gets (optionally) called during Stepping
71+
void initTrackRefHook();
6772

6873
ClassDefOverride(O2MCApplicationBase, 1);
6974
};

Steer/src/O2MCApplication.cxx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
#include <fstream>
2929
#include <FairVolume.h>
3030
#include <CommonUtils/NameConf.h>
31+
#include <CommonUtils/ConfigurationMacroHelper.h>
3132
#include "SimConfig/SimUserDecay.h"
33+
#include <filesystem>
34+
#include <CommonUtils/FileSystemUtils.h>
3235

3336
namespace o2
3437
{
@@ -83,7 +86,11 @@ void O2MCApplicationBase::Stepping()
8386
}
8487
}
8588

86-
// dispatch first to stepping function in FairRoot
89+
if (mCutParams.stepTrackRefHook) {
90+
mTrackRefFcn(fMC);
91+
}
92+
93+
// dispatch now to stepping function in FairRoot
8794
FairMCApplication::Stepping();
8895
}
8996

@@ -1182,6 +1189,22 @@ void O2MCApplicationBase::AddParticles()
11821189
}
11831190
}
11841191

1192+
void O2MCApplicationBase::initTrackRefHook()
1193+
{
1194+
if (mCutParams.stepTrackRefHook) {
1195+
LOG(info) << "Initializing the hook for TrackReferences during stepping";
1196+
auto expandedTrackRefHookFileName = o2::utils::expandShellVarsInFileName(mCutParams.stepTrackRefHookFile);
1197+
if (std::filesystem::exists(expandedTrackRefHookFileName)) {
1198+
// if this file exists we will compile the hook on the fly
1199+
mTrackRefFcn = o2::conf::GetFromMacro<TrackRefFcn>(mCutParams.stepTrackRefHookFile, "trackRefHook()", "o2::steer::O2MCApplicationBase::TrackRefFcn", "o2mc_stepping_trackref_hook");
1200+
LOG(info) << "Hook initialized from file " << expandedTrackRefHookFileName;
1201+
} else {
1202+
LOG(error) << "Did not file TrackRefHook file " << expandedTrackRefHookFileName << " ; Will not execute hook";
1203+
mTrackRefFcn = [](TVirtualMC const*) {}; // do nothing
1204+
}
1205+
}
1206+
}
1207+
11851208
void O2MCApplication::initLate()
11861209
{
11871210
o2::utils::ShmManager::Instance().occupySegment();

0 commit comments

Comments
 (0)