Skip to content

Commit 16d8384

Browse files
jackal1-66alcaliva
authored andcommitted
Trigger implementation in hybrid generator (#13873)
* Trigger implementation in hybrid generator * Added hybrid trigger example (cherry picked from commit 611600b)
1 parent a65822d commit 16d8384

File tree

8 files changed

+299
-41
lines changed

8 files changed

+299
-41
lines changed

Generators/include/Generators/Generator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class Generator : public FairGenerator
7474
virtual Bool_t generateEvent() = 0; // generates event (in structure internal to generator)
7575
virtual Bool_t importParticles() = 0; // fills the mParticles vector (transfer from generator state)
7676
virtual void updateHeader(o2::dataformats::MCEventHeader* eventHeader) {};
77+
Bool_t triggerEvent();
7778

7879
/** setters **/
7980
void setMomentumUnit(double val) { mMomentumUnit = val; };
@@ -106,7 +107,6 @@ class Generator : public FairGenerator
106107
/** internal methods **/
107108
Bool_t addTracks(FairPrimaryGenerator* primGen);
108109
Bool_t boostEvent();
109-
Bool_t triggerEvent();
110110

111111
/** to handle cocktail constituents **/
112112
void addSubGenerator(int subGeneratorId, std::string const& subGeneratorDescription);

Generators/include/Generators/GeneratorHybrid.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ class GeneratorHybrid : public Generator
103103
bool mCocktailMode = false;
104104
std::vector<std::vector<int>> mGroups;
105105

106+
// Trigger configuration
107+
std::vector<ETriggerMode_t> mTriggerModes; // trigger mode for each generator
108+
std::vector<std::vector<std::string>> mTriggerMacros; // trigger macros for each generator (multiple triggers for each generator possible)
109+
std::vector<std::vector<std::string>> mTriggerFuncs; // trigger functions for each generator (multiple triggers for each generator possible)
110+
106111
// Create a task arena with a specified number of threads
107112
std::thread mTBBTaskPoolRunner;
108113
tbb::concurrent_bounded_queue<int> mInputTaskQueue;

Generators/src/GeneratorFactory.cxx

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -293,48 +293,51 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair
293293
}
294294

295295
/** triggers **/
296+
// to be set via GeneratorFactory only if generator is not hybrid
297+
// external settings via JSON are supported in the latter
296298

297299
Trigger trigger = nullptr;
298300
DeepTrigger deeptrigger = nullptr;
299-
300-
auto trgconfig = conf.getTrigger();
301-
if (trgconfig.empty()) {
302-
return;
303-
} else if (trgconfig.compare("particle") == 0) {
304-
trigger = TriggerParticle(TriggerParticleParam::Instance());
305-
} else if (trgconfig.compare("external") == 0) {
306-
// external trigger via configuration macro
307-
auto& params = TriggerExternalParam::Instance();
308-
LOG(info) << "Setting up external trigger with following parameters";
309-
LOG(info) << params;
310-
auto external_trigger_filename = params.fileName;
311-
auto external_trigger_func = params.funcName;
312-
trigger = o2::conf::GetFromMacro<o2::eventgen::Trigger>(external_trigger_filename, external_trigger_func, "o2::eventgen::Trigger", "trigger");
313-
if (!trigger) {
314-
LOG(info) << "Trying to retrieve a \'o2::eventgen::DeepTrigger\' type" << std::endl;
315-
deeptrigger = o2::conf::GetFromMacro<o2::eventgen::DeepTrigger>(external_trigger_filename, external_trigger_func, "o2::eventgen::DeepTrigger", "deeptrigger");
316-
}
317-
if (!trigger && !deeptrigger) {
318-
LOG(fatal) << "Failed to retrieve \'external trigger\': problem with configuration ";
319-
}
320-
} else {
321-
LOG(fatal) << "Invalid trigger";
322-
}
323-
324-
/** add trigger to generators **/
325-
auto generators = primGen->GetListOfGenerators();
326-
for (int igen = 0; igen < generators->GetEntries(); ++igen) {
327-
auto generator = dynamic_cast<o2::eventgen::Generator*>(generators->At(igen));
328-
if (!generator) {
329-
LOG(fatal) << "request to add a trigger to an unsupported generator";
301+
if (!(genconfig.compare("hybrid") == 0)) {
302+
auto trgconfig = conf.getTrigger();
303+
if (trgconfig.empty()) {
330304
return;
305+
} else if (trgconfig.compare("particle") == 0) {
306+
trigger = TriggerParticle(TriggerParticleParam::Instance());
307+
} else if (trgconfig.compare("external") == 0) {
308+
// external trigger via configuration macro
309+
auto& params = TriggerExternalParam::Instance();
310+
LOG(info) << "Setting up external trigger with following parameters";
311+
LOG(info) << params;
312+
auto external_trigger_filename = params.fileName;
313+
auto external_trigger_func = params.funcName;
314+
trigger = o2::conf::GetFromMacro<o2::eventgen::Trigger>(external_trigger_filename, external_trigger_func, "o2::eventgen::Trigger", "trigger");
315+
if (!trigger) {
316+
LOG(info) << "Trying to retrieve a \'o2::eventgen::DeepTrigger\' type" << std::endl;
317+
deeptrigger = o2::conf::GetFromMacro<o2::eventgen::DeepTrigger>(external_trigger_filename, external_trigger_func, "o2::eventgen::DeepTrigger", "deeptrigger");
318+
}
319+
if (!trigger && !deeptrigger) {
320+
LOG(fatal) << "Failed to retrieve \'external trigger\': problem with configuration ";
321+
}
322+
} else {
323+
LOG(fatal) << "Invalid trigger";
331324
}
332-
generator->setTriggerMode(o2::eventgen::Generator::kTriggerOR);
333-
if (trigger) {
334-
generator->addTrigger(trigger);
335-
}
336-
if (deeptrigger) {
337-
generator->addDeepTrigger(deeptrigger);
325+
326+
/** add trigger to generators **/
327+
auto generators = primGen->GetListOfGenerators();
328+
for (int igen = 0; igen < generators->GetEntries(); ++igen) {
329+
auto generator = dynamic_cast<o2::eventgen::Generator*>(generators->At(igen));
330+
if (!generator) {
331+
LOG(fatal) << "request to add a trigger to an unsupported generator";
332+
return;
333+
}
334+
generator->setTriggerMode(o2::eventgen::Generator::kTriggerOR);
335+
if (trigger) {
336+
generator->addTrigger(trigger);
337+
}
338+
if (deeptrigger) {
339+
generator->addDeepTrigger(deeptrigger);
340+
}
338341
}
339342
}
340343
}

Generators/src/GeneratorHybrid.cxx

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,37 @@ Bool_t GeneratorHybrid::Init()
183183
}
184184
gens[count]->Init(); // TODO: move this to multi-threaded
185185
addSubGenerator(count, gen);
186+
if (mTriggerModes[count] != o2::eventgen::Generator::kTriggerOFF) {
187+
gens[count]->setTriggerMode(mTriggerModes[count]);
188+
LOG(info) << "Setting Trigger mode of generator " << gen << " to: " << mTriggerModes[count];
189+
o2::eventgen::Trigger trigger = nullptr;
190+
o2::eventgen::DeepTrigger deeptrigger = nullptr;
191+
for (int trg = 0; trg < mTriggerMacros[count].size(); trg++) {
192+
if (mTriggerMacros[count][trg].empty() || mTriggerFuncs[count][trg].empty()) {
193+
continue;
194+
}
195+
LOG(info) << "Setting trigger " << trg << " of generator " << gen << " with following parameters";
196+
LOG(info) << "Macro filename: " << mTriggerMacros[count][trg];
197+
LOG(info) << "Function name: " << mTriggerFuncs[count][trg];
198+
trigger = o2::conf::GetFromMacro<o2::eventgen::Trigger>(mTriggerMacros[count][trg], mTriggerFuncs[count][trg], "o2::eventgen::Trigger", "trigger");
199+
if (!trigger) {
200+
LOG(info) << "Trying to retrieve a \'o2::eventgen::DeepTrigger\' type";
201+
deeptrigger = o2::conf::GetFromMacro<o2::eventgen::DeepTrigger>(mTriggerMacros[count][trg], mTriggerFuncs[count][trg], "o2::eventgen::DeepTrigger", "deeptrigger");
202+
}
203+
if (!trigger && !deeptrigger) {
204+
LOG(warn) << "Failed to retrieve \'external trigger\': problem with configuration";
205+
LOG(warn) << "Trigger " << trg << " of generator " << gen << " will not be included";
206+
continue;
207+
} else {
208+
LOG(info) << "Trigger " << trg << " of generator " << gen << " successfully set";
209+
}
210+
if (trigger) {
211+
gens[count]->addTrigger(trigger);
212+
} else {
213+
gens[count]->addDeepTrigger(deeptrigger);
214+
}
215+
}
216+
}
186217
count++;
187218
}
188219
if (mRandomize) {
@@ -240,9 +271,13 @@ Bool_t GeneratorHybrid::Init()
240271
// mGenIsInitialized[task] = true;
241272
// }
242273
}
243-
generator->clearParticles();
244-
generator->generateEvent();
245-
generator->importParticles();
274+
bool isTriggered = false;
275+
while (!isTriggered) {
276+
generator->clearParticles();
277+
generator->generateEvent();
278+
generator->importParticles();
279+
isTriggered = generator->triggerEvent();
280+
}
246281
LOG(debug) << "eventgen finished for task " << task;
247282
if (!mStopFlag) {
248283
if (mGenerationMode == GenMode::kParallel) {
@@ -450,6 +485,68 @@ Bool_t GeneratorHybrid::confSetter(const auto& gen)
450485
mConfigs.push_back("");
451486
}
452487
}
488+
if (gen.HasMember("triggers")) {
489+
const auto& trigger = gen["triggers"];
490+
auto trigger_specs = [this, &trigger]() {
491+
mTriggerMacros.push_back({});
492+
mTriggerFuncs.push_back({});
493+
if (trigger.HasMember("specs")) {
494+
for (auto& spec : trigger["specs"].GetArray()) {
495+
if (spec.HasMember("macro")) {
496+
const auto& macro = spec["macro"].GetString();
497+
if (!(strcmp(macro, "") == 0)) {
498+
mTriggerMacros.back().push_back(macro);
499+
} else {
500+
mTriggerMacros.back().push_back("");
501+
}
502+
} else {
503+
mTriggerMacros.back().push_back("");
504+
}
505+
if (spec.HasMember("function")) {
506+
const auto& function = spec["function"].GetString();
507+
if (!(strcmp(function, "") == 0)) {
508+
mTriggerFuncs.back().push_back(function);
509+
} else {
510+
mTriggerFuncs.back().push_back("");
511+
}
512+
} else {
513+
mTriggerFuncs.back().push_back("");
514+
}
515+
}
516+
} else {
517+
mTriggerMacros.back().push_back("");
518+
mTriggerFuncs.back().push_back("");
519+
}
520+
};
521+
if (trigger.HasMember("mode")) {
522+
const auto& trmode = trigger["mode"].GetString();
523+
if (strcmp(trmode, "or") == 0) {
524+
mTriggerModes.push_back(o2::eventgen::Generator::kTriggerOR);
525+
trigger_specs();
526+
} else if (strcmp(trmode, "and") == 0) {
527+
mTriggerModes.push_back(o2::eventgen::Generator::kTriggerAND);
528+
trigger_specs();
529+
} else if (strcmp(trmode, "off") == 0) {
530+
mTriggerModes.push_back(o2::eventgen::Generator::kTriggerOFF);
531+
mTriggerMacros.push_back({""});
532+
mTriggerFuncs.push_back({""});
533+
} else {
534+
LOG(warn) << "Wrong trigger mode provided for generator " << name << ", keeping trigger OFF";
535+
mTriggerModes.push_back(o2::eventgen::Generator::kTriggerOFF);
536+
mTriggerMacros.push_back({""});
537+
mTriggerFuncs.push_back({""});
538+
}
539+
} else {
540+
LOG(warn) << "No trigger mode provided for generator " << name << ", turning trigger OFF";
541+
mTriggerModes.push_back(o2::eventgen::Generator::kTriggerOFF);
542+
mTriggerMacros.push_back({""});
543+
mTriggerFuncs.push_back({""});
544+
}
545+
} else {
546+
mTriggerModes.push_back(o2::eventgen::Generator::kTriggerOFF);
547+
mTriggerMacros.push_back({""});
548+
mTriggerFuncs.push_back({""});
549+
}
453550
return true;
454551
}
455552

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!-- doxy
2+
\page refrunSimExamplesHybrid Example Hybrid
3+
/doxy -->
4+
5+
The usage of the Hybrid generator with the o2-sim is presented in this short manual.
6+
All the other generators are implemented as sub-generators and they can be called thanks to a
7+
JSON file, fed to o2-sim via the GeneratorHybrid.configFile parameter. The O2sim package needs to be loaded in order to use this example.
8+
9+
The example can be run automatically using the runo2sim.sh script, which contains most of the
10+
available generators in O2. The JSON template can be generated using the ${O2DPG_ROOT}/MC/bin/o2_hybrid_gen.py script. To use this example the user can simply copy the entire Hybrid example folder and execute the script after giving it execution permissions (`chmod +x runo2sim.sh`).
11+
12+
# Files description
13+
14+
- **runo2sim.sh** &rarr; allows to use the hybrid generator example
15+
- **hybridconfig.json** &rarr; example JSON file for the hybrid generator configuration
16+
- **example.optns** &rarr; options file to be used in EPOS4 implemented as subgenerator in this example (the .optns must be available in the current working directory)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"generators": [
3+
{
4+
"cocktail": [
5+
{
6+
"name": "pythia8hi",
7+
"triggers": {
8+
"mode": "or",
9+
"specs": [
10+
{
11+
"macro": "${PWD}/trigger.macro",
12+
"function": "trigger_impactb_pythia8(0.,5.)"
13+
}
14+
]
15+
},
16+
"config": ""
17+
},
18+
{
19+
"name": "external",
20+
"config": {
21+
"fileName": "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C",
22+
"funcName": "GeneratorParamPromptJpsiToElectronEvtGen_pp13TeV()",
23+
"iniFile": ""
24+
}
25+
}
26+
]
27+
}
28+
],
29+
"fractions": [
30+
1
31+
]
32+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Hybrid generator simulation example with triggers and cocktail:
4+
# the simulation is configured using a JSON file (hybridconfig.json in this folder), whose
5+
# template can be generated using the script ${O2DPG_ROOT}/MC/bin/o2_hybrid_gen.py.
6+
# Trigger is taken from the trigger.macro and it's a simple impact parameter selection for
7+
# heavy ion collisions
8+
set -x
9+
if [ ! "${O2DPG_ROOT}" ]; then
10+
echo "This needs O2DPG loaded; alienv enter ..."
11+
exit 1
12+
fi
13+
14+
[ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 2
15+
16+
NEV=1
17+
more=""
18+
JOBS=2
19+
20+
usage()
21+
{
22+
cat <<EOF
23+
Usage: $0 [OPTIONS]
24+
25+
Options:
26+
27+
-m,--more CONFIG More configurations ($more)
28+
-n,--nevents EVENTS Number of events ($NEV)
29+
-j,--jobs JOBS Number of jobs ($JOBS)
30+
-h,--help Print these instructions
31+
-- Rest of command line sent to o2-sim
32+
33+
COMMAND must be quoted if it contains spaces or other special
34+
characters
35+
36+
Below follows the help output of o2-sim
37+
38+
EOF
39+
}
40+
41+
if [ "$#" -lt 2 ]; then
42+
echo "Running with default values"
43+
fi
44+
45+
while test $# -gt 0 ; do
46+
case $1 in
47+
-m|--more) more="$2" ; shift ;;
48+
-n|--nevents) NEV=$2 ; shift ;;
49+
-j|--jobs) JOBS=$2 ; shift ;;
50+
-h|--help) usage; o2-sim --help full ; exit 0 ;;
51+
--) shift ; break ;;
52+
*) echo "Unknown option '$1', did you forget '--'?" >/dev/stderr
53+
exit 3
54+
;;
55+
esac
56+
shift
57+
done
58+
59+
# Starting simulation with Hybrid generator
60+
${O2_ROOT}/bin/o2-sim --noGeant -j $JOBS --field ccdb --vertexMode kCCDB --run 300000 --configKeyValues "MFTBase.buildAlignment=true;GeneratorHybrid.configFile=$PWD/hybridconfig.json;GeneratorHybrid.randomize=false;${more}" -g hybrid -o genevents --timestamp 1546300800000 --seed 836302859 -n $NEV

0 commit comments

Comments
 (0)