16#include <fairlogger/Logger.h>
17#include <FairPrimaryGenerator.h>
19#include <TClonesArray.h>
21#include <TMCProcess.h>
35 mEventFile = TFile::Open(
name);
36 if (mEventFile ==
nullptr) {
37 LOG(fatal) <<
"EventFile " <<
name <<
" not found \n";
46 std::stringstream eventstringstr;
47 eventstringstr <<
"Event" << mEventsAvailable;
49 object = mEventFile->Get(eventstringstr.str().c_str());
51 if (
object !=
nullptr) {
54 }
while (
object !=
nullptr);
55 LOG(info) <<
"Found " << mEventsAvailable <<
" events in this file \n";
60 if (
start < mEventsAvailable) {
61 mEventCounter =
start;
63 LOG(error) <<
"start event bigger than available events\n";
71 LOG(warn) <<
"Particle with pdg " << p.GetPdgCode() <<
" not known in DB (not fixing mass)";
76 const auto nominalmass = p.GetMass();
77 auto mom2 = p.Px() * p.Px() + p.Py() * p.Py() + p.Pz() * p.Pz();
78 auto calculatedmass = p.Energy() * p.Energy() - mom2;
79 calculatedmass = (calculatedmass >= 0.) ? std::sqrt(calculatedmass) : -std::sqrt(-calculatedmass);
80 const double tol = 1.E-4;
81 auto difference = std::abs(nominalmass - calculatedmass);
82 if (std::abs(nominalmass - calculatedmass) > tol) {
83 const auto asgmass = p.GetCalcMass();
84 bool fix = mFixOffShell && std::abs(nominalmass - asgmass) < tol;
85 LOG(warn) <<
"Particle " << p.GetPdgCode() <<
" has off-shell mass: M_PDG= " << nominalmass <<
" (assigned= " << asgmass
86 <<
") calculated= " << calculatedmass <<
" -> diff= " << difference <<
" | " << (fix ?
"fixing" :
"skipping");
88 double e = std::sqrt(nominalmass * nominalmass + mom2);
89 p.SetMomentum(p.Px(), p.Py(), p.Pz(), e);
90 p.SetCalcMass(nominalmass);
100 if (mEventCounter < mEventsAvailable) {
101 int particlecounter = 0;
104 std::stringstream treestringstr;
105 treestringstr <<
"Event" << mEventCounter <<
"/TreeK";
106 TTree*
tree = (TTree*)mEventFile->Get(treestringstr.str().c_str());
107 if (
tree ==
nullptr) {
111 auto branch =
tree->GetBranch(
"Particles");
112 TParticle* particle =
nullptr;
113 branch->SetAddress(&particle);
114 LOG(info) <<
"Reading " << branch->GetEntries() <<
" particles from Kinematics file";
117 std::vector<TParticle> particles;
118 for (
int i = 0;
i < branch->GetEntries(); ++
i) {
120 particles.push_back(*particle);
125 auto isFirstTrackableDescendant = [](TParticle
const& p) {
126 const int kTransportBit = BIT(14);
128 if ((p.GetUniqueID() > 0 && p.GetUniqueID() != kPNoProcess) || !p.TestBit(kTransportBit)) {
134 for (
int i = 0;
i < branch->GetEntries(); ++
i) {
135 auto& p = particles[
i];
136 if (!isFirstTrackableDescendant(p)) {
140 bool wanttracking =
true;
141 if (wanttracking || !mSkipNonTrackable) {
145 auto pdgid = p.GetPdgCode();
155 auto weight = p.GetWeight();
156 LOG(
debug) <<
"Putting primary " << pdgid <<
" " << p.GetStatusCode() <<
" " << p.GetUniqueID();
157 primGen->AddTrack(pdgid, px, py, pz, vx, vy, vz, parent, wanttracking, e, tof,
weight);
163 LOG(info) <<
"Event generator put " << particlecounter <<
" on stack";
166 LOG(error) <<
"GeneratorFromFile: Ran out of events\n";
181 if (strncmp(
name,
"alien:/", 7) == 0 && !gGrid) {
182 TGrid::Connect(
"alien:");
184 LOG(fatal) <<
"Could not connect to alien, did you check the alien token?";
188 mEventFile = TFile::Open(
name);
189 if (mEventFile ==
nullptr) {
190 LOG(fatal) <<
"EventFile " <<
name <<
" not found";
195 auto tree = (TTree*)mEventFile->Get(
"o2sim");
197 mEventBranch =
tree->GetBranch(
"MCTrack");
199 mEventsAvailable = mEventBranch->GetEntries();
200 LOG(info) <<
"Found " << mEventsAvailable <<
" events in this file";
202 mMCHeaderBranch =
tree->GetBranch(
"MCEventHeader.");
203 if (mMCHeaderBranch) {
204 LOG(info) <<
"Found " << mMCHeaderBranch->GetEntries() <<
" event-headers";
206 LOG(warn) <<
"No MCEventHeader branch found in kinematics input file";
210 LOG(error) <<
"Problem reading events from file " <<
name;
215 mConfig = std::make_unique<O2KineGenConfig>(pars);
223 LOG(info) <<
"Init \'FromO2Kine\' generator";
224 mSkipNonTrackable = mConfig->skipNonTrackable;
225 mContinueMode = mConfig->continueMode;
226 mRoundRobin = mConfig->roundRobin;
227 mRandomize = mConfig->randomize;
228 mRngSeed = mConfig->rngseed;
229 mRandomPhi = mConfig->randomphi;
231 gRandom->SetSeed(mRngSeed);
239 if (
start < mEventsAvailable) {
240 mEventCounter =
start;
242 LOG(error) <<
"start event bigger than available events\n";
254 mEventCounter = gRandom->Integer(mEventsAvailable);
255 LOG(info) <<
"GeneratorFromO2Kine - Picking event " << mEventCounter;
261 dPhi = gRandom->Uniform(2 * TMath::Pi());
262 LOG(info) <<
"Rotating phi by " << dPhi;
265 if (mEventCounter < mEventsAvailable) {
266 int particlecounter = 0;
268 std::vector<o2::MCTrack>* tracks =
nullptr;
269 mEventBranch->SetAddress(&tracks);
270 mEventBranch->GetEntry(mEventCounter);
272 if (mMCHeaderBranch) {
274 mMCHeaderBranch->SetAddress(&mcheader);
275 mMCHeaderBranch->GetEntry(mEventCounter);
276 mOrigMCEventHeader.reset(mcheader);
279 for (
auto& t : *tracks) {
282 if (!mContinueMode && !t.isPrimary()) {
286 auto pdg = t.GetPdgCode();
291 auto cos = TMath::Cos(dPhi);
292 auto sin = TMath::Sin(dPhi);
293 auto newPx = px * cos - py * sin;
294 auto newPy = px * sin + py * cos;
302 auto m1 = t.getMotherTrackId();
303 auto m2 = t.getSecondMotherTrackId();
304 auto d1 = t.getFirstDaughterTrackId();
305 auto d2 = t.getLastDaughterTrackId();
306 auto e = t.GetEnergy();
307 auto vt = t.T() * 1e-9;
308 auto weight = t.getWeight();
309 auto wanttracking = t.getToBeDone();
312 wanttracking &= t.getInhibited();
315 LOG(
debug) <<
"Putting primary " << pdg;
317 mParticles.push_back(TParticle(pdg, t.getStatusCode().fullEncoding, m1, m2, d1, d2, px, py, pz, e, vx, vy, vz, vt));
318 mParticles.back().SetUniqueID((
unsigned int)t.getProcess());
326 LOG(info) <<
"Resetting event counter to 0; Reusing events from file";
327 mEventCounter = mEventCounter % mEventsAvailable;
334 LOG(info) <<
"Event generator put " << particlecounter <<
" on stack";
337 LOG(error) <<
"GeneratorFromO2Kine: Ran out of events\n";
347 if (mOrigMCEventHeader.get()) {
354 eventHeader->
putInfo<std::string>(
"forwarding-generator",
"generatorFromO2Kine");
355 eventHeader->
putInfo<std::string>(
"forwarding-generator_inputFile", mEventFile->GetName());
356 eventHeader->
putInfo<
int>(
"forwarding-generator_inputEventNumber", mEventCounter - 1);
362std::vector<std::string> executeCommand(
const std::string& command)
364 std::vector<std::string>
result;
365 std::unique_ptr<FILE,
int (*)(FILE*)> pipe(popen(command.c_str(),
"r"), pclose);
367 throw std::runtime_error(
"Failed to open pipe");
371 while (fgets(
buffer,
sizeof(
buffer), pipe.get()) !=
nullptr) {
374 if (!line.empty() && line.back() ==
'\n') {
396 mRandomEngine.seed(mConfig.
rngseed);
398 std::random_device
rd;
399 mRandomEngine.seed(
rd());
402 gSystem->ExpandPathName(expPath);
405 if (mPoolFilesAvailable.size() == 0) {
406 LOG(error) <<
"No file found that can be used with EventPool generator";
409 LOG(info) <<
"Found " << mPoolFilesAvailable.size() <<
" available event pool files";
412 std::uniform_int_distribution<int> distribution(0, mPoolFilesAvailable.size() - 1);
413 auto chosenIndex = distribution(mRandomEngine);
414 mFileChosen = mPoolFilesAvailable[chosenIndex];
415 LOG(info) <<
"EventPool is using file " << mFileChosen;
420 .continueMode =
false,
425 .fileName = mFileChosen};
427 return mO2KineGenerator->Init();
432namespace fs = std::filesystem;
434bool checkFileName(std::string
const& pathStr)
439 const std::string protocol =
"alien://";
440 std::string finalPathStr(pathStr);
441 if (pathStr.starts_with(protocol)) {
442 finalPathStr = pathStr.substr(protocol.size());
444 fs::path
path(finalPathStr);
448 }
catch (
const fs::filesystem_error& e) {
450 std::cerr <<
"Filesystem error: " << e.what() <<
'\n';
454 std::cerr <<
"An unknown error occurred while checking the path.\n";
460bool checkFileUniverse(std::vector<std::string>
const& universe)
462 if (universe.size() == 0) {
465 for (
auto& fn : universe) {
466 if (!checkFileName(fn)) {
475std::vector<std::string> readLines(
const std::string& filePath)
477 std::vector<std::string> lines;
480 fs::path
path(filePath);
483 std::ifstream
file(filePath);
484 if (!
file.is_open()) {
485 throw std::ios_base::failure(
"Failed to open the file.");
490 while (std::getline(file, line)) {
491 lines.push_back(line);
497std::vector<std::string> getLocalFileList(
const fs::path& rootPath)
499 std::vector<std::string>
result;
502 if (!fs::exists(rootPath) || !fs::is_directory(rootPath)) {
503 throw std::invalid_argument(
"The provided path is not a valid directory.");
507 for (
const auto&
entry : fs::recursive_directory_iterator(rootPath)) {
523 std::vector<std::string>
result;
529 auto alienStatTypeCommand = std::string(
"alien.py stat ") + mConfig.
eventPoolPath + std::string(
" 2>/dev/null | grep Type ");
530 auto typeString = executeCommand(alienStatTypeCommand);
531 if (typeString.size() == 0) {
533 }
else if (typeString.size() == 1 && typeString.front() == std::string(
"Type: f")) {
537 }
else if (typeString.size() == 1 && typeString.front() == std::string(
"Type: d")) {
540 std::string alienSearchCommand = std::string(
"alien.py find ") +
543 auto universe_vector = executeCommand(alienSearchCommand);
545 if (!checkFileUniverse(universe_vector)) {
548 for (
auto&
f : universe_vector) {
552 return universe_vector;
554 LOG(error) <<
"Unsupported file type";
560 auto is_actual_file = std::filesystem::is_regular_file(
path);
561 if (is_actual_file) {
563 if (checkFileName(
path)) {
564 TFile rootfile(
path.c_str(),
"OPEN");
565 if (!rootfile.IsZombie()) {
571 auto files = readLines(
path);
572 if (checkFileUniverse(files)) {
580 auto is_dir = std::filesystem::is_directory(
path);
584 auto files = getLocalFileList(
path);
585 if (checkFileUniverse(files)) {
ClassImp(o2::eventgen::GeneratorFromEventPool)
Definition of the MCTrack class.
GeneratorFromEventPool()=default
static constexpr std::string_view eventpool_filename
static constexpr std::string_view alien_protocol_prefix
std::vector< std::string > setupFileUniverse(std::string const &path) const
GeneratorFromFile()=default
void SetStartEvent(int start)
bool rejectOrFixKinematics(TParticle &p)
bool ReadEvent(FairPrimaryGenerator *primGen) override
void SetStartEvent(int start)
void updateHeader(o2::dataformats::MCEventHeader *eventHeader) override
bool importParticles() override
GeneratorFromO2Kine()=default
void setPositionUnit(double val)
void setEnergyUnit(double val)
void setTimeUnit(double val)
std::vector< TParticle > mParticles
void setMomentumUnit(double val)
GLuint const GLchar * name
GLuint GLuint GLfloat weight
GLsizei const GLchar *const * path
int32_t const char * file
int32_t const char int32_t line
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string eventPoolPath
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))