From 8585daaa357a288a32e498a6fd3101e978fd598e Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Fri, 15 Nov 2024 10:55:11 +0100 Subject: [PATCH] Created EPOS4 external example generator (#1789) * Created EPOS4 external example generator * Updated center-of-mass energy of EPOS4 example * Implemented GeneratorEPOS4 test * Testing fix for EPOS4 external * Revert "Implemented GeneratorEPOS4 test" This reverts commit e0b88b19613cedc016d497df211d8338257caba9. * Reapply "Implemented GeneratorEPOS4 test" This reverts commit 53671e82f12a5b4886d859a1e12f859000ad3fb4. * Revert "Testing fix for EPOS4 external" This reverts commit 920cf42cf3cb006814792cf90b606919b9fde3ee. * Check for LIBDIR * Added EPO4 as env variable in external script * Explicit definition of EPOS4 version * Reorganised and improved fix for CI --- MC/config/examples/epos4/epos.sh | 41 ++++++++++++ .../examples/epos4/generator/example.optns | 32 ++++++++++ MC/config/examples/epos4/generator_EPOS4.C | 61 ++++++++++++++++++ MC/config/examples/ini/GeneratorEPOS4.ini | 10 +++ MC/config/examples/ini/tests/GeneratorEPOS4.C | 64 +++++++++++++++++++ 5 files changed, 208 insertions(+) create mode 100755 MC/config/examples/epos4/epos.sh create mode 100644 MC/config/examples/epos4/generator/example.optns create mode 100644 MC/config/examples/epos4/generator_EPOS4.C create mode 100644 MC/config/examples/ini/GeneratorEPOS4.ini create mode 100644 MC/config/examples/ini/tests/GeneratorEPOS4.C diff --git a/MC/config/examples/epos4/epos.sh b/MC/config/examples/epos4/epos.sh new file mode 100755 index 000000000..c416e03f7 --- /dev/null +++ b/MC/config/examples/epos4/epos.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# Script based on CRMC example +# EPOS4 option files must contain ihepmc set to 2 to print HepMC +# data on stdout. -hepmc flag is not needed anymore, but -hepstd is fundamental +# in order not to print useless information on stdout (a z-*optns*.mtr file will be created) + +optns="example" +seed=$RANDOM + +while test $# -gt 0 ; do + case $1 in + -i|--input) optns=$2 ; shift ;; + -s|--seed) seed=$2 ; shift ;; + -h|--help) usage; exit 0 ;; + esac + shift +done + +if [ ! -f $optns.optns ]; then + echo "Error: Options file $optns.optns not found" + exit 1 +fi + +if [ $seed -eq 0 ]; then + echo "Seed can't be 0, random number will be used" + seed=$RANDOM +fi + +# Check if the environment variable EPO4 is set (mandatory with o2dpg-sim-tests on CI machines) +# If not, set all the EPOS4 related variables, most likely they are unset as well. +if [ -z "${EPO4}" ]; then + export EPO4=$EPOS4_ROOT/epos4/ + export LIBDIR=$EPOS4_ROOT/epos4/bin + export EPO4VSN=4.0.0 + export OPT=./ + export HTO=./ + export CHK=./ +fi + +# Or filters the stdout with only HepMC2 useful data +$EPOS4_ROOT/epos4/scripts/epos -hepstd -s $seed $optns | sed -n 's/^\(HepMC::\|[EAUWVP] \)/\1/p' diff --git a/MC/config/examples/epos4/generator/example.optns b/MC/config/examples/epos4/generator/example.optns new file mode 100644 index 000000000..0b97d4f52 --- /dev/null +++ b/MC/config/examples/epos4/generator/example.optns @@ -0,0 +1,32 @@ +!-------------------------------------------------------------------- +! proton-proton collision no hydro no hadronic cascade +!-------------------------------------------------------------------- + +!--------------------------------------- +! Define run +!--------------------------------------- + +application hadron !hadron-hadron, hadron-nucleus, or nucleus-nucleus +set laproj 1 !projectile atomic number +set maproj 1 !projectile mass number +set latarg 1 !target atomic number +set matarg 1 !target mass number +set ecms 13600 !sqrt(s)_pp +set istmax 25 !max status considered for storage + +ftime on !string formation time non-zero +!suppressed decays: +nodecays + 110 20 2130 -2130 2230 -2230 1130 -1130 1330 -1330 2330 -2330 3331 -3331 +end + +set ninicon 1 !number of initial conditions used for hydro evolution +core off !core/corona not activated +hydro off !hydro not activated +eos off !eos not activated +hacas off !hadronic cascade not activated +set nfreeze 1 !number of freeze out events per hydro event +set modsho 1 !printout every modsho events +set centrality 0 !0=min bias +set ihepmc 2 !HepMC output enabled on stdout +set nfull 10 diff --git a/MC/config/examples/epos4/generator_EPOS4.C b/MC/config/examples/epos4/generator_EPOS4.C new file mode 100644 index 000000000..6d08a7b19 --- /dev/null +++ b/MC/config/examples/epos4/generator_EPOS4.C @@ -0,0 +1,61 @@ +#include +#include +#include +#include + +class GeneratorEPOS4 : public o2::eventgen::GeneratorHepMC +{ + public: + GeneratorEPOS4() = default; + ~GeneratorEPOS4() = default; + +}; + +// Next function takes the optns file as argument and edits the maximum number of events to be generated. +// When used as an external generator it is important that the events passed with the -n flag are the same +// or lower of the events set in the optns file, otherwise the generation will crash. That is why the .ini +// example file contains the maximum integer available, assuming less events than that are generated in a real +// life scenario. Unfortunately a larger number cannot be used at the moment since EPOS4 has a signed integer +// type for the nfull parameter. Might be changed in the future. +// When running locally, or on the GRID (not in hyperloop), the default parameters provided in the .ini file of the +// external generation can be overwritten using the confKeyValues option (or similar depending on the tool used). +FairGenerator* generateEPOS4(const std::string &name, const int& nEvents) +{ + // check if the file exists + auto filename = gSystem->ExpandPathName(name.c_str()); + if (!std::filesystem::exists(filename)) + { + LOG(fatal) << "Options file " << filename << " does not exist!"; + exit(1); + } + // cache all the lines of the optns file and replace the number of events + std::ifstream file(filename); + std::string line; + bool found = false; + std::stringstream buffer; + while (std::getline(file, line)) + { + if (line.find("nfull") != std::string::npos){ + // replace the number of events + found = true; + line = "set nfull " + std::to_string(nEvents); + } + buffer << line << "\n"; + } + file.close(); + // Write the updated content back to a file in the current directory + std::ofstream outFile("cfg.optns"); + outFile << buffer.str(); + if (!found) + { + outFile << "set nfull " + std::to_string(nEvents); + } + outFile.close(); + auto gen = new GeneratorEPOS4(); + auto& param0 = o2::eventgen::GeneratorFileOrCmdParam::Instance(); + auto& param = o2::eventgen::GeneratorHepMCParam::Instance(); + auto& conf = o2::conf::SimConfig::Instance(); + // setup the HepMC generator to run with automatic FIFOs + gen->setup(param0, param, conf); + return gen; +} diff --git a/MC/config/examples/ini/GeneratorEPOS4.ini b/MC/config/examples/ini/GeneratorEPOS4.ini new file mode 100644 index 000000000..33935cbe2 --- /dev/null +++ b/MC/config/examples/ini/GeneratorEPOS4.ini @@ -0,0 +1,10 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C +funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/example.optns", 2147483647) + +[GeneratorFileOrCmd] +cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh -i cfg +bMaxSwitch=none + +[HepMC] +version=2 \ No newline at end of file diff --git a/MC/config/examples/ini/tests/GeneratorEPOS4.C b/MC/config/examples/ini/tests/GeneratorEPOS4.C new file mode 100644 index 000000000..5f735eddf --- /dev/null +++ b/MC/config/examples/ini/tests/GeneratorEPOS4.C @@ -0,0 +1,64 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // Check if there are 100 events, as simulated in the o2dpg-test + if (nEvents != 100) + { + std::cerr << "Expected 100 events, got " << nEvents << "\n"; + return 1; + } + // check if each event has two protons with 6800 GeV of energy + // exits if the particle is not a proton + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + int count = 0; + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + double energy = track.GetEnergy(); + // Check if track energy is approximately equal to 6800 GeV (a tolerance of 65 keV is considered, straight equality does not work due to floating point precision) + if (std::abs(energy - 6800) < 1e-4) + { + if (track.GetPdgCode() != 2212){ + std::cerr << "Found 6800 GeV particle with pdgID " << track.GetPdgCode() << "\n"; + return 1; + } + count++; + } + } + if (count < 2) + { + std::cerr << "Event " << i << " has less than 2 protons at 6800 GeV\n"; + return 1; + } + } + return 0; +} \ No newline at end of file