Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trigger implementation in hybrid generator #13873

Merged
merged 4 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Generators/include/Generators/Generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class Generator : public FairGenerator
virtual Bool_t generateEvent() = 0; // generates event (in structure internal to generator)
virtual Bool_t importParticles() = 0; // fills the mParticles vector (transfer from generator state)
virtual void updateHeader(o2::dataformats::MCEventHeader* eventHeader) {};
Bool_t triggerEvent();

/** setters **/
void setMomentumUnit(double val) { mMomentumUnit = val; };
Expand Down Expand Up @@ -106,7 +107,6 @@ class Generator : public FairGenerator
/** internal methods **/
Bool_t addTracks(FairPrimaryGenerator* primGen);
Bool_t boostEvent();
Bool_t triggerEvent();

/** to handle cocktail constituents **/
void addSubGenerator(int subGeneratorId, std::string const& subGeneratorDescription);
Expand Down
5 changes: 5 additions & 0 deletions Generators/include/Generators/GeneratorHybrid.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ class GeneratorHybrid : public Generator
bool mCocktailMode = false;
std::vector<std::vector<int>> mGroups;

// Trigger configuration
std::vector<ETriggerMode_t> mTriggerModes; // trigger mode for each generator
std::vector<std::vector<std::string>> mTriggerMacros; // trigger macros for each generator (multiple triggers for each generator possible)
std::vector<std::vector<std::string>> mTriggerFuncs; // trigger functions for each generator (multiple triggers for each generator possible)

// Create a task arena with a specified number of threads
std::thread mTBBTaskPoolRunner;
tbb::concurrent_bounded_queue<int> mInputTaskQueue;
Expand Down
77 changes: 40 additions & 37 deletions Generators/src/GeneratorFactory.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -293,48 +293,51 @@ void GeneratorFactory::setPrimaryGenerator(o2::conf::SimConfig const& conf, Fair
}

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

Trigger trigger = nullptr;
DeepTrigger deeptrigger = nullptr;

auto trgconfig = conf.getTrigger();
if (trgconfig.empty()) {
return;
} else if (trgconfig.compare("particle") == 0) {
trigger = TriggerParticle(TriggerParticleParam::Instance());
} else if (trgconfig.compare("external") == 0) {
// external trigger via configuration macro
auto& params = TriggerExternalParam::Instance();
LOG(info) << "Setting up external trigger with following parameters";
LOG(info) << params;
auto external_trigger_filename = params.fileName;
auto external_trigger_func = params.funcName;
trigger = o2::conf::GetFromMacro<o2::eventgen::Trigger>(external_trigger_filename, external_trigger_func, "o2::eventgen::Trigger", "trigger");
if (!trigger) {
LOG(info) << "Trying to retrieve a \'o2::eventgen::DeepTrigger\' type" << std::endl;
deeptrigger = o2::conf::GetFromMacro<o2::eventgen::DeepTrigger>(external_trigger_filename, external_trigger_func, "o2::eventgen::DeepTrigger", "deeptrigger");
}
if (!trigger && !deeptrigger) {
LOG(fatal) << "Failed to retrieve \'external trigger\': problem with configuration ";
}
} else {
LOG(fatal) << "Invalid trigger";
}

/** add trigger to generators **/
auto generators = primGen->GetListOfGenerators();
for (int igen = 0; igen < generators->GetEntries(); ++igen) {
auto generator = dynamic_cast<o2::eventgen::Generator*>(generators->At(igen));
if (!generator) {
LOG(fatal) << "request to add a trigger to an unsupported generator";
if (!(genconfig.compare("hybrid") == 0)) {
auto trgconfig = conf.getTrigger();
if (trgconfig.empty()) {
return;
} else if (trgconfig.compare("particle") == 0) {
trigger = TriggerParticle(TriggerParticleParam::Instance());
} else if (trgconfig.compare("external") == 0) {
// external trigger via configuration macro
auto& params = TriggerExternalParam::Instance();
LOG(info) << "Setting up external trigger with following parameters";
LOG(info) << params;
auto external_trigger_filename = params.fileName;
auto external_trigger_func = params.funcName;
trigger = o2::conf::GetFromMacro<o2::eventgen::Trigger>(external_trigger_filename, external_trigger_func, "o2::eventgen::Trigger", "trigger");
if (!trigger) {
LOG(info) << "Trying to retrieve a \'o2::eventgen::DeepTrigger\' type" << std::endl;
deeptrigger = o2::conf::GetFromMacro<o2::eventgen::DeepTrigger>(external_trigger_filename, external_trigger_func, "o2::eventgen::DeepTrigger", "deeptrigger");
}
if (!trigger && !deeptrigger) {
LOG(fatal) << "Failed to retrieve \'external trigger\': problem with configuration ";
}
} else {
LOG(fatal) << "Invalid trigger";
}
generator->setTriggerMode(o2::eventgen::Generator::kTriggerOR);
if (trigger) {
generator->addTrigger(trigger);
}
if (deeptrigger) {
generator->addDeepTrigger(deeptrigger);

/** add trigger to generators **/
auto generators = primGen->GetListOfGenerators();
for (int igen = 0; igen < generators->GetEntries(); ++igen) {
auto generator = dynamic_cast<o2::eventgen::Generator*>(generators->At(igen));
if (!generator) {
LOG(fatal) << "request to add a trigger to an unsupported generator";
return;
}
generator->setTriggerMode(o2::eventgen::Generator::kTriggerOR);
if (trigger) {
generator->addTrigger(trigger);
}
if (deeptrigger) {
generator->addDeepTrigger(deeptrigger);
}
}
}
}
Expand Down
103 changes: 100 additions & 3 deletions Generators/src/GeneratorHybrid.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,37 @@ Bool_t GeneratorHybrid::Init()
}
gens[count]->Init(); // TODO: move this to multi-threaded
addSubGenerator(count, gen);
if (mTriggerModes[count] != o2::eventgen::Generator::kTriggerOFF) {
gens[count]->setTriggerMode(mTriggerModes[count]);
LOG(info) << "Setting Trigger mode of generator " << gen << " to: " << mTriggerModes[count];
o2::eventgen::Trigger trigger = nullptr;
o2::eventgen::DeepTrigger deeptrigger = nullptr;
for (int trg = 0; trg < mTriggerMacros[count].size(); trg++) {
if (mTriggerMacros[count][trg].empty() || mTriggerFuncs[count][trg].empty()) {
continue;
}
LOG(info) << "Setting trigger " << trg << " of generator " << gen << " with following parameters";
LOG(info) << "Macro filename: " << mTriggerMacros[count][trg];
LOG(info) << "Function name: " << mTriggerFuncs[count][trg];
trigger = o2::conf::GetFromMacro<o2::eventgen::Trigger>(mTriggerMacros[count][trg], mTriggerFuncs[count][trg], "o2::eventgen::Trigger", "trigger");
if (!trigger) {
LOG(info) << "Trying to retrieve a \'o2::eventgen::DeepTrigger\' type";
deeptrigger = o2::conf::GetFromMacro<o2::eventgen::DeepTrigger>(mTriggerMacros[count][trg], mTriggerFuncs[count][trg], "o2::eventgen::DeepTrigger", "deeptrigger");
}
if (!trigger && !deeptrigger) {
LOG(warn) << "Failed to retrieve \'external trigger\': problem with configuration";
LOG(warn) << "Trigger " << trg << " of generator " << gen << " will not be included";
continue;
} else {
LOG(info) << "Trigger " << trg << " of generator " << gen << " successfully set";
}
if (trigger) {
gens[count]->addTrigger(trigger);
} else {
gens[count]->addDeepTrigger(deeptrigger);
}
}
}
count++;
}
if (mRandomize) {
Expand Down Expand Up @@ -240,9 +271,13 @@ Bool_t GeneratorHybrid::Init()
// mGenIsInitialized[task] = true;
// }
}
generator->clearParticles();
generator->generateEvent();
generator->importParticles();
bool isTriggered = false;
while (!isTriggered) {
generator->clearParticles();
generator->generateEvent();
generator->importParticles();
isTriggered = generator->triggerEvent();
}
LOG(debug) << "eventgen finished for task " << task;
if (!mStopFlag) {
if (mGenerationMode == GenMode::kParallel) {
Expand Down Expand Up @@ -450,6 +485,68 @@ Bool_t GeneratorHybrid::confSetter(const auto& gen)
mConfigs.push_back("");
}
}
if (gen.HasMember("triggers")) {
const auto& trigger = gen["triggers"];
auto trigger_specs = [this, &trigger]() {
mTriggerMacros.push_back({});
mTriggerFuncs.push_back({});
if (trigger.HasMember("specs")) {
for (auto& spec : trigger["specs"].GetArray()) {
if (spec.HasMember("macro")) {
const auto& macro = spec["macro"].GetString();
if (!(strcmp(macro, "") == 0)) {
mTriggerMacros.back().push_back(macro);
} else {
mTriggerMacros.back().push_back("");
}
} else {
mTriggerMacros.back().push_back("");
}
if (spec.HasMember("function")) {
const auto& function = spec["function"].GetString();
if (!(strcmp(function, "") == 0)) {
mTriggerFuncs.back().push_back(function);
} else {
mTriggerFuncs.back().push_back("");
}
} else {
mTriggerFuncs.back().push_back("");
}
}
} else {
mTriggerMacros.back().push_back("");
mTriggerFuncs.back().push_back("");
}
};
if (trigger.HasMember("mode")) {
const auto& trmode = trigger["mode"].GetString();
if (strcmp(trmode, "or") == 0) {
mTriggerModes.push_back(o2::eventgen::Generator::kTriggerOR);
trigger_specs();
} else if (strcmp(trmode, "and") == 0) {
mTriggerModes.push_back(o2::eventgen::Generator::kTriggerAND);
trigger_specs();
} else if (strcmp(trmode, "off") == 0) {
mTriggerModes.push_back(o2::eventgen::Generator::kTriggerOFF);
mTriggerMacros.push_back({""});
mTriggerFuncs.push_back({""});
} else {
LOG(warn) << "Wrong trigger mode provided for generator " << name << ", keeping trigger OFF";
mTriggerModes.push_back(o2::eventgen::Generator::kTriggerOFF);
mTriggerMacros.push_back({""});
mTriggerFuncs.push_back({""});
}
} else {
LOG(warn) << "No trigger mode provided for generator " << name << ", turning trigger OFF";
mTriggerModes.push_back(o2::eventgen::Generator::kTriggerOFF);
mTriggerMacros.push_back({""});
mTriggerFuncs.push_back({""});
}
} else {
mTriggerModes.push_back(o2::eventgen::Generator::kTriggerOFF);
mTriggerMacros.push_back({""});
mTriggerFuncs.push_back({""});
}
return true;
}

Expand Down
16 changes: 16 additions & 0 deletions run/SimExamples/Hybrid_trigger/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!-- doxy
\page refrunSimExamplesHybrid Example Hybrid
/doxy -->

The usage of the Hybrid generator with the o2-sim is presented in this short manual.
All the other generators are implemented as sub-generators and they can be called thanks to a
JSON file, fed to o2-sim via the GeneratorHybrid.configFile parameter. The O2sim package needs to be loaded in order to use this example.

The example can be run automatically using the runo2sim.sh script, which contains most of the
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`).

# Files description

- **runo2sim.sh** &rarr; allows to use the hybrid generator example
- **hybridconfig.json** &rarr; example JSON file for the hybrid generator configuration
- **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)
32 changes: 32 additions & 0 deletions run/SimExamples/Hybrid_trigger/hybridconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"generators": [
{
"cocktail": [
{
"name": "pythia8hi",
"triggers": {
"mode": "or",
"specs": [
{
"macro": "${PWD}/trigger.macro",
"function": "trigger_impactb_pythia8(0.,5.)"
}
]
},
"config": ""
},
{
"name": "external",
"config": {
"fileName": "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C",
"funcName": "GeneratorParamPromptJpsiToElectronEvtGen_pp13TeV()",
"iniFile": ""
}
}
]
}
],
"fractions": [
1
]
}
60 changes: 60 additions & 0 deletions run/SimExamples/Hybrid_trigger/runo2sim.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env bash
#
# Hybrid generator simulation example with triggers and cocktail:
# the simulation is configured using a JSON file (hybridconfig.json in this folder), whose
# template can be generated using the script ${O2DPG_ROOT}/MC/bin/o2_hybrid_gen.py.
# Trigger is taken from the trigger.macro and it's a simple impact parameter selection for
# heavy ion collisions
set -x
if [ ! "${O2DPG_ROOT}" ]; then
echo "This needs O2DPG loaded; alienv enter ..."
exit 1
fi

[ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 2

NEV=1
more=""
JOBS=2

usage()
{
cat <<EOF
Usage: $0 [OPTIONS]
Options:
-m,--more CONFIG More configurations ($more)
-n,--nevents EVENTS Number of events ($NEV)
-j,--jobs JOBS Number of jobs ($JOBS)
-h,--help Print these instructions
-- Rest of command line sent to o2-sim
COMMAND must be quoted if it contains spaces or other special
characters
Below follows the help output of o2-sim
EOF
}

if [ "$#" -lt 2 ]; then
echo "Running with default values"
fi

while test $# -gt 0 ; do
case $1 in
-m|--more) more="$2" ; shift ;;
-n|--nevents) NEV=$2 ; shift ;;
-j|--jobs) JOBS=$2 ; shift ;;
-h|--help) usage; o2-sim --help full ; exit 0 ;;
--) shift ; break ;;
*) echo "Unknown option '$1', did you forget '--'?" >/dev/stderr
exit 3
;;
esac
shift
done

# Starting simulation with Hybrid generator
${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
Loading
Loading