Skip to content

Commit e3f1edc

Browse files
Benedikt Volkelsawenzel
authored andcommitted
[MCReplay] Updates
* optionally allow to handle StopTrack * make skipTrack time-dependent instead of simple bool This allows to skip also tracks that would have followed later after a StopTrack request was issued * Move some functionality to functions
1 parent 462fceb commit e3f1edc

File tree

2 files changed

+142
-72
lines changed

2 files changed

+142
-72
lines changed

MCReplay/include/MCReplay/MCReplayEngine.h

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,11 @@ class MCReplayEngine : public TVirtualMC
11191119
mUpdateProcessesCutsBlocked = value;
11201120
}
11211121

1122+
void allowStopTrack(bool value = true)
1123+
{
1124+
mAllowStopTrack = value;
1125+
}
1126+
11221127
void cutsFromConfig(std::string const& path);
11231128

11241129
private:
@@ -1150,21 +1155,26 @@ class MCReplayEngine : public TVirtualMC
11501155
// treat a user secondary that was, for instance, pushed to the stack during hit creation
11511156
void transportUserHitSecondary();
11521157

1158+
bool startTrack(const o2::StepInfo& step);
1159+
void finishTrack(const o2::StepInfo& nextStep);
1160+
void finishTrack();
1161+
bool stepping();
1162+
11531163
// helper function to derive a hash from step properties to seed gRandom
11541164
// On the shoulders of o2::data::Stack
11551165
ULong_t makeHash(const o2::StepInfo& step) const;
11561166

11571167
// add process or cut values based on name and value
11581168
template <typename P, typename T, std::size_t N>
1159-
bool insertProcessOrCut(std::vector<std::vector<P>*>& insertInto, const std::array<T, N>& allParamsNames, const std::vector<P>& defaultParams, Int_t mediumId, const char* paramName, P parval)
1169+
bool insertProcessOrCut(std::vector<std::vector<P>*>& insertInto, const std::array<T, N>& allParamsNames, const std::vector<P>& defaultParams, Int_t mediumId, const char* paramName, P parval, bool forceSet=false)
11601170
{
11611171
auto paramIndex = physics::paramToIndex(allParamsNames, paramName);
1162-
return insertProcessOrCut(insertInto, allParamsNames, defaultParams, mediumId, paramIndex, parval);
1172+
return insertProcessOrCut(insertInto, allParamsNames, defaultParams, mediumId, paramIndex, parval, forceSet);
11631173
}
11641174

11651175
// add process or cut values based on name and value
11661176
template <typename P, typename T, std::size_t N>
1167-
bool insertProcessOrCut(std::vector<std::vector<P>*>& insertInto, const std::array<T, N>& allParamsNames, const std::vector<P>& defaultParams, Int_t mediumId, int paramIndex, P parval)
1177+
bool insertProcessOrCut(std::vector<std::vector<P>*>& insertInto, const std::array<T, N>& allParamsNames, const std::vector<P>& defaultParams, Int_t mediumId, int paramIndex, P parval, bool forceSet=false)
11681178
{
11691179
if (paramIndex < 0) {
11701180
return false;
@@ -1178,24 +1188,32 @@ class MCReplayEngine : public TVirtualMC
11781188
if (!currMap) {
11791189
currMap = new std::vector<P>(defaultParams.begin(), defaultParams.end());
11801190
}
1181-
(*currMap)[paramIndex] = parval;
1191+
auto& value = (*currMap)[paramIndex];
1192+
if (value >= 0 && !forceSet) {
1193+
return false;
1194+
}
1195+
value = parval;
11821196
return true;
11831197
}
11841198

11851199
template <typename P, typename T, std::size_t N>
1186-
bool insertProcessOrCut(std::vector<P>& insertInto, const std::array<T, N>& allParamsNames, const char* paramName, P parval)
1200+
bool insertProcessOrCut(std::vector<P>& insertInto, const std::array<T, N>& allParamsNames, const char* paramName, P parval, bool forceSet=false)
11871201
{
11881202
auto paramIndex = physics::paramToIndex(allParamsNames, paramName);
1189-
return insertProcessOrCut(insertInto, allParamsNames, paramIndex, parval);
1203+
return insertProcessOrCut(insertInto, allParamsNames, paramIndex, parval, forceSet);
11901204
}
11911205

11921206
template <typename P, typename T, std::size_t N>
1193-
bool insertProcessOrCut(std::vector<P>& insertInto, const std::array<T, N>& allParamsNames, int paramIndex, P parval)
1207+
bool insertProcessOrCut(std::vector<P>& insertInto, const std::array<T, N>& allParamsNames, int paramIndex, P parval, bool forceSet=false)
11941208
{
11951209
if (paramIndex < 0) {
11961210
return false;
11971211
}
1198-
insertInto[paramIndex] = parval;
1212+
auto& value = insertInto[paramIndex];
1213+
if (value >= 0 && !forceSet) {
1214+
return false;
1215+
}
1216+
value = parval;
11991217
return true;
12001218
}
12011219

@@ -1211,6 +1229,9 @@ class MCReplayEngine : public TVirtualMC
12111229
bool mIsEventStopped = false;
12121230
bool mIsTrackStopped = false;
12131231

1232+
// If we allow for stoopping a track
1233+
bool mAllowStopTrack = true;
1234+
12141235
// File and tree name to process
12151236
std::string mStepLoggerFilename;
12161237
std::string mStepLoggerTreename;
@@ -1237,7 +1258,7 @@ class MCReplayEngine : public TVirtualMC
12371258
o2::StepInfo* mCurrentStep = nullptr;
12381259

12391260
// keep track of tracks to be skipped
1240-
std::vector<bool> mSkipTrack;
1261+
std::vector<float> mSkipTrack;
12411262
// keep track of track ID assigned by user stack
12421263
std::vector<int> mUserTrackId;
12431264

@@ -1247,7 +1268,12 @@ class MCReplayEngine : public TVirtualMC
12471268
// increment the current track length
12481269
float mCurrentTrackLength = 0.;
12491270

1250-
// block in case framework should be prevented from setting cuts or processes
1271+
// keep track of primary tracks
1272+
int mCurrentPrimaryId = -1;
1273+
// keep track of current track
1274+
int mCurrentTrackId = -1;
1275+
1276+
// block in case the using framework should be prevented from setting cuts or processes
12511277
bool mUpdateProcessesCutsBlocked = false;
12521278
// Preliminary process structure
12531279
std::vector<std::vector<Int_t>*> mProcesses;

MCReplay/src/MCReplayEngine.cxx

Lines changed: 106 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ int MCReplayEngine::getMediumId(int volId) const
743743
Bool_t MCReplayEngine::SetProcess(const char* flagName, Int_t flagValue)
744744
{
745745
if (mUpdateProcessesCutsBlocked) {
746-
::Info("MCReplayEngine::Gstpar", "Parameter setting closed, nothing is changed.");
746+
::Info("MCReplayEngine::SetProcess", "Parameter setting closed, nothing is changed.");
747747
return false;
748748
}
749749
return insertProcessOrCut(mProcessesGlobal, physics::namesCuts, flagName, flagValue);
@@ -752,10 +752,18 @@ Bool_t MCReplayEngine::SetProcess(const char* flagName, Int_t flagValue)
752752
Bool_t MCReplayEngine::SetCut(const char* cutName, Double_t cutValue)
753753
{
754754
if (mUpdateProcessesCutsBlocked) {
755-
::Info("MCReplayEngine::Gstpar", "Parameter setting closed, nothing is changed.");
755+
::Info("MCReplayEngine::SetCut", "Parameter setting closed, nothing is changed.");
756756
return false;
757757
}
758-
return insertProcessOrCut(mCutsGlobal, physics::namesCuts, cutName, cutValue);
758+
auto setGlobal = insertProcessOrCut(mCutsGlobal, physics::namesCuts, cutName, cutValue);
759+
return setGlobal;
760+
for (auto& mediumCuts : mCuts) {
761+
if (!mediumCuts) {
762+
continue;
763+
}
764+
insertProcessOrCut(*mediumCuts, physics::namesCuts, cutName, cutValue);
765+
}
766+
return setGlobal;
759767
}
760768

761769
Int_t MCReplayEngine::CurrentVolID(Int_t& copyNo) const
@@ -893,14 +901,15 @@ void MCReplayEngine::Gstpar(Int_t itmed, const char* param, Double_t parval)
893901
::Info("MCReplayEngine::Gstpar", "Parameter setting closed, nothing is changed.");
894902
return;
895903
}
896-
if (insertProcessOrCut(mProcesses, physics::namesProcesses, mProcessesGlobal, itmed, param, (int)parval)) {
904+
if (insertProcessOrCut(mProcesses, physics::namesProcesses, mProcessesGlobal, itmed, param, (int)parval, true)) {
897905
return;
898906
}
899-
if (!insertProcessOrCut(mCuts, physics::namesCuts, mCutsGlobal, itmed, param, parval)) {
907+
if (!insertProcessOrCut(mCuts, physics::namesCuts, mCutsGlobal, itmed, param, parval, true)) {
900908
::Warning("MCReplayEngine::Gstpar", "Could not set parameter %s, unknown and therefore skipped", param);
901909
}
902910
}
903911

912+
904913
void MCReplayEngine::loadCurrentCutsAndProcesses(int volId)
905914
{
906915
mCurrentProcesses = &mProcessesGlobal;
@@ -985,36 +994,97 @@ bool MCReplayEngine::initRun()
985994

986995
void MCReplayEngine::transportUserHitSecondary()
987996
{
988-
// For now we just start and finish this secondary. This is only done to pretend the transport for the user stack
997+
// secondaries that are somehow produced by the framework (e.g. during hit creation) cannot be taken into accoun.
998+
// Since we rely on pre-recorded steps, we can only pretend to account for them.
989999
fApplication->PreTrack();
9901000
fApplication->PostTrack();
9911001
}
9921002

1003+
bool MCReplayEngine::startTrack(const o2::StepInfo& step)
1004+
{
1005+
mStack->SetCurrentTrack(mUserTrackId[step.trackID]);
1006+
mCurrentTrackLength = 0.;
1007+
1008+
if (isPrimary(step.trackID)) {
1009+
mCurrentPrimaryId = step.trackID;
1010+
fApplication->BeginPrimary();
1011+
}
1012+
mCurrentTrackId = step.trackID;
1013+
fApplication->PreTrack();
1014+
gRandom->SetSeed(makeHash(step));
1015+
1016+
if (!keepStep(step)) {
1017+
mSkipTrack[step.trackID] = step.t;
1018+
return false;
1019+
}
1020+
return true;
1021+
}
1022+
1023+
void MCReplayEngine::finishTrack(const o2::StepInfo& nextStep)
1024+
{
1025+
if (mCurrentTrackId > -1) {
1026+
fApplication->PostTrack();
1027+
}
1028+
if (isPrimary(nextStep.trackID) && mCurrentPrimaryId >= 0) {
1029+
fApplication->FinishPrimary();
1030+
}
1031+
}
1032+
1033+
void MCReplayEngine::finishTrack()
1034+
{
1035+
if (mCurrentTrackId >= 0) {
1036+
fApplication->PostTrack();
1037+
mCurrentTrackId = -1;
1038+
}
1039+
if (mCurrentPrimaryId > -1) {
1040+
fApplication->FinishPrimary();
1041+
mCurrentPrimaryId = -1;
1042+
}
1043+
}
1044+
1045+
bool MCReplayEngine::stepping()
1046+
{
1047+
fApplication->Stepping();
1048+
// now let's see if the track was stopped for some reason
1049+
if (mIsTrackStopped) {
1050+
// reset the flag for the next track to come
1051+
mIsTrackStopped = false;
1052+
if (mAllowStopTrack) {
1053+
mSkipTrack[mCurrentStep->trackID] = mCurrentStep->t;
1054+
return false;
1055+
}
1056+
}
1057+
return true;
1058+
}
1059+
9931060
void MCReplayEngine::ProcessEvent(Int_t eventId)
9941061
{
995-
// prepare
996-
std::vector<o2::StepInfo>* steps = nullptr;
1062+
// at this point, we do not allow any process or cut settings anymore from the outside
1063+
blockSetProcessesCuts();
1064+
std::vector<o2::StepInfo>* steps{};
9971065
mCurrentLookups = nullptr;
9981066
mStepBranch->SetAddress(&steps);
9991067
mLookupBranch->SetAddress(&mCurrentLookups);
10001068
mStepBranch->GetEvent(eventId);
10011069
mLookupBranch->GetEvent(eventId);
10021070

10031071
// whether or not to skip certain tracks
1004-
mSkipTrack.resize(mCurrentLookups->tracktopdg.size(), false);
1072+
mSkipTrack.resize(mCurrentLookups->tracktopdg.size(), -1.);
10051073
// we need to make sure we follow the indexing of the user stack. During the original simulation, there might have been more tracks pushed than transported. In the replay case, we only have the tracks that have been originally transported. Hence, the indexing this time might be different.
10061074
mUserTrackId.resize(mCurrentLookups->tracktopdg.size(), -1);
1007-
// some caching to be able to run pre- and post-hooks at the right time
1008-
int currentTrackId = -1;
1075+
std::cout << "Number of PDGs: " << mUserTrackId.size() << std::endl;
1076+
// cache track and primary IDs during stepping
1077+
mCurrentTrackId = -1;
1078+
mCurrentPrimaryId = -1;
10091079

1080+
// preparation done, start replay
10101081
fApplication->BeginEvent();
10111082
fApplication->GeneratePrimaries();
10121083

10131084
// Remember how many primaries are expected to be transported
10141085
auto expectedNPrimaries = mStack->GetNprimary();
10151086

1016-
/* SOME REMARKS
1017-
1087+
/*
10181088
1. Steps are expected to be grouped together track-by-track (that comes from the MCStepLogger and will only work properly for the serial simulation run)
10191089
2. Therefore, if a step with a different track ID is reached, it is assumed that the previous track is finished
10201090
3. Since in the original reference run, some secondaries might have been pushed to the user stack but not transported, we comply with the track ID assignement of the user stack in a replay run
@@ -1029,59 +1099,44 @@ void MCReplayEngine::ProcessEvent(Int_t eventId)
10291099
TStopwatch stopwatch{};
10301100

10311101
for (auto& step : *steps) {
1032-
1033-
// TODO This should not happen. (see comment in header file for these flags)
10341102
if (mIsEventStopped) {
10351103
mIsEventStopped = false;
10361104
::Warning("MCReplayEngine::ProcessEvent", "Event %d was stopped. That should usually not happen", mCurrentEvent);
10371105
break;
10381106
}
10391107

1040-
mSkipTrack[step.trackID] = !step.newtrack && mSkipTrack[step.trackID];
1108+
mSkipTrack[step.trackID] = !step.newtrack && mSkipTrack[step.trackID] >= 0. ? mSkipTrack[step.trackID] : -1.;
10411109

10421110
// skip if flagged and increment
1043-
if (mSkipTrack[step.trackID]) {
1111+
if (mSkipTrack[step.trackID] >= 0.) {
10441112
continue;
10451113
}
1046-
if (mCurrentLookups->tracktoparent[step.trackID] > -1 && mSkipTrack[mCurrentLookups->tracktoparent[step.trackID]]) {
1047-
// skip recursively in case parent was skipped, only affects secondaries of course
1048-
mSkipTrack[step.trackID] = true;
1049-
continue;
1114+
if (mCurrentLookups->tracktoparent[step.trackID] > -1) {
1115+
auto parentTime = mSkipTrack[mCurrentLookups->tracktoparent[step.trackID]];
1116+
if (parentTime >= 0 && parentTime <= step.t) {
1117+
// skip recursively in case parent was skipped, only affects secondaries of course
1118+
mSkipTrack[step.trackID] = step.t;
1119+
continue;
1120+
}
10501121
}
1051-
10521122
if (step.entered || step.newtrack) {
10531123
// find the correct set of cuts and processes for this volume
10541124
loadCurrentCutsAndProcesses(step.volId);
10551125
mGeoManager->cd(step.geopath->c_str());
10561126
}
10571127

10581128
// NOW PERFORM EVERYTHIN NECESSARY TO START / FINISH A TRACK
1129+
if (mCurrentTrackId != step.trackID) {
10591130

1060-
if (currentTrackId == step.trackID && mIsTrackStopped) {
1061-
// track can be told to be stopped in replay run due to different states of RNGs of reference and replay run, will be ignored
1062-
nStopTrack++;
1063-
mIsTrackStopped = false;
1064-
}
1065-
1066-
if (currentTrackId != step.trackID) {
1067-
// Found a new track
1068-
1069-
auto prim = isPrimary(step.trackID);
1131+
// Finish potential last track
1132+
finishTrack(step);
10701133

1071-
if (currentTrackId > -1) {
1072-
// only invoke if there has been at least 1 track before
1073-
fApplication->PostTrack();
1074-
if (prim) {
1075-
// finish previous primary only in case all its secondary tracks have been transported and a new primary is about to be transported
1076-
fApplication->FinishPrimary();
1077-
}
1078-
}
1079-
1080-
if (!prim) {
1134+
if (!isPrimary(step.trackID)) {
10811135
// decide to skip this secondary immediately, primaries must be popped first since otherwise we might run into inconsitencies with the user stack
10821136
// therefore, it looks as if this secondary never appeared
10831137
if (!keepStep(step)) {
1084-
mSkipTrack[step.trackID] = true;
1138+
mSkipTrack[step.trackID] = step.t;
1139+
mCurrentTrackId = -1;
10851140
continue;
10861141
}
10871142

@@ -1105,35 +1160,22 @@ void MCReplayEngine::ProcessEvent(Int_t eventId)
11051160
mUserTrackId[step.trackID] = popTrackId;
11061161
}
11071162

1108-
currentTrackId = step.trackID;
1109-
mStack->SetCurrentTrack(mUserTrackId[step.trackID]);
1110-
mCurrentTrackLength = 0.;
1111-
1112-
if (prim) {
1113-
fApplication->BeginPrimary();
1114-
}
1115-
fApplication->PreTrack();
1116-
1117-
if (!keepStep(step)) {
1118-
// This is for primaries since secondaries would have been skipped already above
1119-
mSkipTrack[step.trackID] = true;
1163+
if (!startTrack(step)) {
11201164
continue;
11211165
}
1122-
1123-
// We fix the RNG so in case the hits are somehow based on that, the hits among different Replay runs are exactly reproduced
1124-
gRandom->SetSeed(makeHash(step));
11251166
}
11261167

11271168
mCurrentTrackLength += step.step;
11281169
mCurrentStep = &step;
11291170

1171+
if (!stepping()) {
1172+
continue;
1173+
}
11301174
nStepsKept++;
1131-
fApplication->Stepping();
11321175
}
11331176

11341177
// Finish last track and the entire event
1135-
fApplication->PostTrack();
1136-
fApplication->FinishPrimary();
1178+
finishTrack();
11371179

11381180
fApplication->FinishEvent();
11391181

@@ -1142,7 +1184,9 @@ void MCReplayEngine::ProcessEvent(Int_t eventId)
11421184
auto nStepsSkipped = steps->size() - nStepsKept;
11431185
std::cout << "Original number, skipped, kept, skipped fraction and kept fraction of steps: " << steps->size() << " " << nStepsSkipped << " " << nStepsKept << " " << static_cast<float>(nStepsSkipped) / steps->size() << " " << static_cast<float>(nStepsKept) / steps->size() << "\n";
11441186
std::cout << "In addition, " << nUserTracks << " tracks produced during hit creation were ignored\n";
1145-
std::cout << "TVirtualMC::StopTrack was ignored " << nStopTrack << " times\n";
1187+
if (!mAllowStopTrack) {
1188+
std::cout << "TVirtualMC::StopTrack was ignored " << nStopTrack << " times\n";
1189+
}
11461190
std::cout << "Real time: " << stopwatch.RealTime() << ", CPU time: " << stopwatch.CpuTime() << "\n";
11471191

11481192
delete steps;

0 commit comments

Comments
 (0)