2222#include < TParticle.h>
2323#include < TTree.h>
2424#include < sstream>
25+ #include < filesystem>
26+ #include < TGrid.h>
2527
2628namespace o2
2729{
@@ -249,6 +251,7 @@ bool GeneratorFromO2Kine::importParticles()
249251 // Randomize the order of events in the input file
250252 if (mRandomize ) {
251253 mEventCounter = gRandom ->Integer (mEventsAvailable );
254+ LOG (info) << " GeneratorFromO2Kine - Picking event " << mEventCounter ;
252255 }
253256
254257 double dPhi = 0 .;
@@ -352,8 +355,236 @@ void GeneratorFromO2Kine::updateHeader(o2::dataformats::MCEventHeader* eventHead
352355 eventHeader->putInfo <int >(" forwarding-generator_inputEventNumber" , mEventCounter - 1 );
353356}
354357
358+ namespace
359+ {
360+ // some helper to execute a command and capture it's output in a vector
361+ std::vector<std::string> executeCommand (const std::string& command)
362+ {
363+ std::vector<std::string> result;
364+ std::unique_ptr<FILE, decltype (&pclose)> pipe (popen (command.c_str (), " r" ), pclose);
365+ if (!pipe) {
366+ throw std::runtime_error (" Failed to open pipe" );
367+ }
368+
369+ char buffer[1024 ];
370+ while (fgets (buffer, sizeof (buffer), pipe.get ()) != nullptr ) {
371+ std::string line (buffer);
372+ // Remove trailing newline character, if any
373+ if (!line.empty () && line.back () == ' \n ' ) {
374+ line.pop_back ();
375+ }
376+ result.push_back (line);
377+ }
378+ return result;
379+ }
380+ } // namespace
381+
382+ GeneratorFromEventPool::GeneratorFromEventPool (EventPoolGenConfig const & pars) : mConfig {pars}
383+ {
384+ }
385+
386+ bool GeneratorFromEventPool::Init ()
387+ {
388+ // initialize the event pool
389+ if (mConfig .rngseed > 0 ) {
390+ mRandomEngine .seed (mConfig .rngseed );
391+ } else {
392+ std::random_device rd;
393+ mRandomEngine .seed (rd ());
394+ }
395+ mPoolFilesAvailable = setupFileUniverse (mConfig .eventPoolPath );
396+
397+ if (mPoolFilesAvailable .size () == 0 ) {
398+ LOG (error) << " No file found that can be used with EventPool generator" ;
399+ return false ;
400+ }
401+
402+ // now choose the actual file
403+ std::uniform_int_distribution<int > distribution (0 , mPoolFilesAvailable .size ());
404+ mFileChosen = mPoolFilesAvailable [distribution (mRandomEngine )];
405+ LOG (info) << " EventPool is using file " << mFileChosen ;
406+
407+ // we bring up the internal mO2KineGenerator
408+ auto kine_config = O2KineGenConfig{
409+ .skipNonTrackable = mConfig .skipNonTrackable ,
410+ .continueMode = false ,
411+ .roundRobin = false ,
412+ .randomize = mConfig .randomize ,
413+ .rngseed = mConfig .rngseed ,
414+ .randomphi = mConfig .randomphi ,
415+ .fileName = mFileChosen };
416+ mO2KineGenerator .reset (new GeneratorFromO2Kine (kine_config));
417+ return mO2KineGenerator ->Init ();
418+ }
419+
420+ namespace
421+ {
422+ namespace fs = std::filesystem;
423+ // checks a single file name
424+ bool checkFileName (std::string const & pathStr)
425+ {
426+ // LOG(info) << "Checking filename " << pathStr;
427+ try {
428+ // Remove optional protocol prefix "alien://"
429+ const std::string protocol = " alien://" ;
430+ std::string finalPathStr (pathStr);
431+ if (pathStr.starts_with (protocol)) {
432+ finalPathStr = pathStr.substr (protocol.size ());
433+ }
434+ fs::path path (finalPathStr);
435+
436+ // Check if the filename is "eventpool.root"
437+ return path.filename () == GeneratorFromEventPool::eventpool_filename;
438+ } catch (const fs::filesystem_error& e) {
439+ // Invalid path syntax will throw an exception
440+ std::cerr << " Filesystem error: " << e.what () << ' \n ' ;
441+ return false ;
442+ } catch (...) {
443+ // Catch-all for other potential exceptions
444+ std::cerr << " An unknown error occurred while checking the path.\n " ;
445+ return false ;
446+ }
447+ }
448+
449+ // checks a whole universe of file names
450+ bool checkFileUniverse (std::vector<std::string> const & universe)
451+ {
452+ if (universe.size () == 0 ) {
453+ return false ;
454+ }
455+ for (auto & fn : universe) {
456+ if (!checkFileName (fn)) {
457+ return false ;
458+ }
459+ }
460+ // TODO: also check for a common path structure with maximally 00X as only difference
461+
462+ return true ;
463+ }
464+
465+ std::vector<std::string> readLines (const std::string& filePath)
466+ {
467+ std::vector<std::string> lines;
468+
469+ // Check if the file is a valid text file
470+ fs::path path (filePath);
471+
472+ // Open the file
473+ std::ifstream file (filePath);
474+ if (!file.is_open ()) {
475+ throw std::ios_base::failure (" Failed to open the file." );
476+ }
477+
478+ // Read up to n lines
479+ std::string line;
480+ while (std::getline (file, line)) {
481+ lines.push_back (line);
482+ }
483+ return lines;
484+ }
485+
486+ // Function to find all files named eventpool_filename under a given path
487+ std::vector<std::string> getLocalFileList (const fs::path& rootPath)
488+ {
489+ std::vector<std::string> result;
490+
491+ // Ensure the root path exists and is a directory
492+ if (!fs::exists (rootPath) || !fs::is_directory (rootPath)) {
493+ throw std::invalid_argument (" The provided path is not a valid directory." );
494+ }
495+
496+ // Iterate over the directory and subdirectories
497+ for (const auto & entry : fs::recursive_directory_iterator (rootPath)) {
498+ if (entry.is_regular_file () && entry.path ().filename () == GeneratorFromEventPool::eventpool_filename) {
499+ result.push_back (entry.path ().string ());
500+ }
501+ }
502+ return result;
503+ }
504+
505+ } // end anonymous namespace
506+
507+ // / A function determining the universe of event pool files, as determined by the path string
508+ // / returns empty vector if it fails
509+ std::vector<std::string> GeneratorFromEventPool::setupFileUniverse (std::string const & path) const
510+ {
511+
512+ // the path could refer to a local or alien filesystem; find out first
513+ bool onAliEn = strncmp (path.c_str (), alien_protocol_prefix.c_str (), alien_protocol_prefix.size ()) == 0 ;
514+ std::vector<std::string> result;
515+
516+ if (onAliEn) {
517+ // AliEn case
518+ // we support: (a) an actual evtgen file and (b) a path containing multiple eventfiles
519+
520+ auto alienStatTypeCommand = std::string (" alien.py stat " ) + mConfig .eventPoolPath + std::string (" 2>/dev/null | grep Type " );
521+ auto typeString = executeCommand (alienStatTypeCommand);
522+ if (typeString.size () == 0 ) {
523+ return result;
524+ } else if (typeString.size () == 1 && typeString.front () == std::string (" Type: f" )) {
525+ // this is a file ... simply use it
526+ result.push_back (mConfig .eventPoolPath );
527+ return result;
528+ } else if (typeString.size () == 1 && typeString.front () == std::string (" Type: d" )) {
529+ // this is a directory
530+ // construct command to find actual event files
531+ std::string alienSearchCommand = std::string (" alien.py find " ) +
532+ mConfig .eventPoolPath + " / " + eventpool_filename;
533+
534+ auto universe_vector = executeCommand (alienSearchCommand);
535+ // check vector
536+ if (!checkFileUniverse (universe_vector)) {
537+ return result;
538+ }
539+ for (auto & f : universe_vector) {
540+ f = alien_protocol_prefix + f;
541+ }
542+
543+ return universe_vector;
544+ } else {
545+ LOG (error) << " Unsupported file type" ;
546+ return result;
547+ }
548+ } else {
549+ // local file case
550+ // check if the path is a regular file
551+ auto is_actual_file = std::filesystem::is_regular_file (path);
552+ if (is_actual_file) {
553+ // The files must match a criteria of being canonical paths ending with eventpool_Kine.root
554+ if (checkFileName (path)) {
555+ TFile rootfile (path.c_str (), " OPEN" );
556+ if (!rootfile.IsZombie ()) {
557+ result.push_back (path);
558+ return result;
559+ }
560+ } else {
561+ // otherwise assume it is a text file containing a list of files themselves
562+ auto files = readLines (path);
563+ if (checkFileUniverse (files)) {
564+ result = files;
565+ return result;
566+ }
567+ }
568+ } else {
569+ // check if the path is just a path
570+ // In this case we need to search something and check
571+ auto is_dir = std::filesystem::is_directory (path);
572+ if (!is_dir) {
573+ return result;
574+ }
575+ auto files = getLocalFileList (path);
576+ if (checkFileUniverse (files)) {
577+ result = files;
578+ return result;
579+ }
580+ }
581+ }
582+ return result;
583+ }
584+
355585} // namespace eventgen
356586} // end namespace o2
357587
588+ ClassImp (o2::eventgen::GeneratorFromEventPool);
358589ClassImp (o2::eventgen::GeneratorFromFile);
359- ClassImp (o2::eventgen::GeneratorFromO2Kine);
590+ ClassImp (o2::eventgen::GeneratorFromO2Kine);
0 commit comments