16#include <fairlogger/Logger.h>
17#include <FairPrimaryGenerator.h>
19#include <TClonesArray.h>
21#include <TMCProcess.h>
34 mEventFile = TFile::Open(
name);
35 if (mEventFile ==
nullptr) {
36 LOG(fatal) <<
"EventFile " <<
name <<
" not found \n";
45 std::stringstream eventstringstr;
46 eventstringstr <<
"Event" << mEventsAvailable;
48 object = mEventFile->Get(eventstringstr.str().c_str());
50 if (
object !=
nullptr) {
53 }
while (
object !=
nullptr);
54 LOG(info) <<
"Found " << mEventsAvailable <<
" events in this file \n";
59 if (
start < mEventsAvailable) {
60 mEventCounter =
start;
62 LOG(error) <<
"start event bigger than available events\n";
70 LOG(warn) <<
"Particle with pdg " << p.GetPdgCode() <<
" not known in DB (not fixing mass)";
75 const auto nominalmass = p.GetMass();
76 auto mom2 = p.Px() * p.Px() + p.Py() * p.Py() + p.Pz() * p.Pz();
77 auto calculatedmass = p.Energy() * p.Energy() - mom2;
78 calculatedmass = (calculatedmass >= 0.) ? std::sqrt(calculatedmass) : -std::sqrt(-calculatedmass);
79 const double tol = 1.E-4;
80 auto difference = std::abs(nominalmass - calculatedmass);
81 if (std::abs(nominalmass - calculatedmass) > tol) {
82 const auto asgmass = p.GetCalcMass();
83 bool fix = mFixOffShell && std::abs(nominalmass - asgmass) < tol;
84 LOG(warn) <<
"Particle " << p.GetPdgCode() <<
" has off-shell mass: M_PDG= " << nominalmass <<
" (assigned= " << asgmass
85 <<
") calculated= " << calculatedmass <<
" -> diff= " << difference <<
" | " << (fix ?
"fixing" :
"skipping");
87 double e = std::sqrt(nominalmass * nominalmass + mom2);
88 p.SetMomentum(p.Px(), p.Py(), p.Pz(), e);
89 p.SetCalcMass(nominalmass);
99 if (mEventCounter < mEventsAvailable) {
100 int particlecounter = 0;
103 std::stringstream treestringstr;
104 treestringstr <<
"Event" << mEventCounter <<
"/TreeK";
105 TTree*
tree = (TTree*)mEventFile->Get(treestringstr.str().c_str());
106 if (
tree ==
nullptr) {
110 auto branch =
tree->GetBranch(
"Particles");
111 TParticle* particle =
nullptr;
112 branch->SetAddress(&particle);
113 LOG(info) <<
"Reading " << branch->GetEntries() <<
" particles from Kinematics file";
116 std::vector<TParticle> particles;
117 for (
int i = 0;
i < branch->GetEntries(); ++
i) {
119 particles.push_back(*particle);
124 auto isFirstTrackableDescendant = [](TParticle
const& p) {
125 const int kTransportBit = BIT(14);
127 if ((p.GetUniqueID() > 0 && p.GetUniqueID() != kPNoProcess) || !p.TestBit(kTransportBit)) {
133 for (
int i = 0;
i < branch->GetEntries(); ++
i) {
134 auto& p = particles[
i];
135 if (!isFirstTrackableDescendant(p)) {
139 bool wanttracking =
true;
140 if (wanttracking || !mSkipNonTrackable) {
144 auto pdgid = p.GetPdgCode();
154 auto weight = p.GetWeight();
155 LOG(
debug) <<
"Putting primary " << pdgid <<
" " << p.GetStatusCode() <<
" " << p.GetUniqueID();
156 primGen->AddTrack(pdgid, px, py, pz, vx, vy, vz, parent, wanttracking, e, tof,
weight);
162 LOG(info) <<
"Event generator put " << particlecounter <<
" on stack";
165 LOG(error) <<
"GeneratorFromFile: Ran out of events\n";
180 if (strncmp(
name,
"alien:/", 7) == 0) {
181 mAlienInstance = TGrid::Connect(
"alien");
182 if (!mAlienInstance) {
183 LOG(fatal) <<
"Could not connect to alien, did you check the alien token?";
187 mEventFile = TFile::Open(
name);
188 if (mEventFile ==
nullptr) {
189 LOG(fatal) <<
"EventFile " <<
name <<
" not found";
194 auto tree = (TTree*)mEventFile->Get(
"o2sim");
196 mEventBranch =
tree->GetBranch(
"MCTrack");
198 mEventsAvailable = mEventBranch->GetEntries();
199 LOG(info) <<
"Found " << mEventsAvailable <<
" events in this file";
201 mMCHeaderBranch =
tree->GetBranch(
"MCEventHeader.");
202 if (mMCHeaderBranch) {
203 LOG(info) <<
"Found " << mMCHeaderBranch->GetEntries() <<
" event-headers";
205 LOG(warn) <<
"No MCEventHeader branch found in kinematics input file";
209 LOG(error) <<
"Problem reading events from file " <<
name;
214 mConfig = std::make_unique<O2KineGenConfig>(pars);
222 LOG(info) <<
"Init \'FromO2Kine\' generator";
223 mSkipNonTrackable = mConfig->skipNonTrackable;
224 mContinueMode = mConfig->continueMode;
225 mRoundRobin = mConfig->roundRobin;
226 mRandomize = mConfig->randomize;
227 mRngSeed = mConfig->rngseed;
228 mRandomPhi = mConfig->randomphi;
230 gRandom->SetSeed(mRngSeed);
238 if (
start < mEventsAvailable) {
239 mEventCounter =
start;
241 LOG(error) <<
"start event bigger than available events\n";
253 mEventCounter = gRandom->Integer(mEventsAvailable);
254 LOG(info) <<
"GeneratorFromO2Kine - Picking event " << mEventCounter;
260 dPhi = gRandom->Uniform(2 * TMath::Pi());
261 LOG(info) <<
"Rotating phi by " << dPhi;
264 if (mEventCounter < mEventsAvailable) {
265 int particlecounter = 0;
267 std::vector<o2::MCTrack>* tracks =
nullptr;
268 mEventBranch->SetAddress(&tracks);
269 mEventBranch->GetEntry(mEventCounter);
271 if (mMCHeaderBranch) {
273 mMCHeaderBranch->SetAddress(&mcheader);
274 mMCHeaderBranch->GetEntry(mEventCounter);
275 mOrigMCEventHeader.reset(mcheader);
278 for (
auto& t : *tracks) {
281 if (!mContinueMode && !t.isPrimary()) {
285 auto pdg = t.GetPdgCode();
290 auto cos = TMath::Cos(dPhi);
291 auto sin = TMath::Sin(dPhi);
292 auto newPx = px * cos - py * sin;
293 auto newPy = px * sin + py * cos;
301 auto m1 = t.getMotherTrackId();
302 auto m2 = t.getSecondMotherTrackId();
303 auto d1 = t.getFirstDaughterTrackId();
304 auto d2 = t.getLastDaughterTrackId();
305 auto e = t.GetEnergy();
306 auto vt = t.T() * 1e-9;
307 auto weight = t.getWeight();
308 auto wanttracking = t.getToBeDone();
311 wanttracking &= t.getInhibited();
314 LOG(
debug) <<
"Putting primary " << pdg;
316 mParticles.push_back(TParticle(pdg, t.getStatusCode().fullEncoding, m1, m2, d1, d2, px, py, pz, e, vx, vy, vz, vt));
317 mParticles.back().SetUniqueID((
unsigned int)t.getProcess());
325 LOG(info) <<
"Resetting event counter to 0; Reusing events from file";
326 mEventCounter = mEventCounter % mEventsAvailable;
333 LOG(info) <<
"Event generator put " << particlecounter <<
" on stack";
336 LOG(error) <<
"GeneratorFromO2Kine: Ran out of events\n";
346 if (mOrigMCEventHeader.get()) {
353 eventHeader->
putInfo<std::string>(
"forwarding-generator",
"generatorFromO2Kine");
354 eventHeader->
putInfo<std::string>(
"forwarding-generator_inputFile", mEventFile->GetName());
355 eventHeader->
putInfo<
int>(
"forwarding-generator_inputEventNumber", mEventCounter - 1);
361std::vector<std::string> executeCommand(
const std::string& command)
363 std::vector<std::string>
result;
364 std::unique_ptr<FILE,
decltype(&pclose)> pipe(popen(command.c_str(),
"r"), pclose);
366 throw std::runtime_error(
"Failed to open pipe");
370 while (fgets(
buffer,
sizeof(
buffer), pipe.get()) !=
nullptr) {
373 if (!line.empty() && line.back() ==
'\n') {
390 mRandomEngine.seed(mConfig.
rngseed);
392 std::random_device
rd;
393 mRandomEngine.seed(
rd());
397 if (mPoolFilesAvailable.size() == 0) {
398 LOG(error) <<
"No file found that can be used with EventPool generator";
401 LOG(info) <<
"Found " << mPoolFilesAvailable.size() <<
" available event pool files";
404 std::uniform_int_distribution<int> distribution(0, mPoolFilesAvailable.size() - 1);
405 auto chosenIndex = distribution(mRandomEngine);
406 mFileChosen = mPoolFilesAvailable[chosenIndex];
407 LOG(info) <<
"EventPool is using file " << mFileChosen;
412 .continueMode =
false,
417 .fileName = mFileChosen};
419 return mO2KineGenerator->Init();
424namespace fs = std::filesystem;
426bool checkFileName(std::string
const& pathStr)
431 const std::string protocol =
"alien://";
432 std::string finalPathStr(pathStr);
433 if (pathStr.starts_with(protocol)) {
434 finalPathStr = pathStr.substr(protocol.size());
436 fs::path
path(finalPathStr);
440 }
catch (
const fs::filesystem_error& e) {
442 std::cerr <<
"Filesystem error: " << e.what() <<
'\n';
446 std::cerr <<
"An unknown error occurred while checking the path.\n";
452bool checkFileUniverse(std::vector<std::string>
const& universe)
454 if (universe.size() == 0) {
457 for (
auto& fn : universe) {
458 if (!checkFileName(fn)) {
467std::vector<std::string> readLines(
const std::string& filePath)
469 std::vector<std::string> lines;
472 fs::path
path(filePath);
475 std::ifstream
file(filePath);
476 if (!
file.is_open()) {
477 throw std::ios_base::failure(
"Failed to open the file.");
482 while (std::getline(
file, line)) {
483 lines.push_back(line);
489std::vector<std::string> getLocalFileList(
const fs::path& rootPath)
491 std::vector<std::string>
result;
494 if (!fs::exists(rootPath) || !fs::is_directory(rootPath)) {
495 throw std::invalid_argument(
"The provided path is not a valid directory.");
499 for (
const auto&
entry : fs::recursive_directory_iterator(rootPath)) {
515 std::vector<std::string>
result;
521 auto alienStatTypeCommand = std::string(
"alien.py stat ") + mConfig.
eventPoolPath + std::string(
" 2>/dev/null | grep Type ");
522 auto typeString = executeCommand(alienStatTypeCommand);
523 if (typeString.size() == 0) {
525 }
else if (typeString.size() == 1 && typeString.front() == std::string(
"Type: f")) {
529 }
else if (typeString.size() == 1 && typeString.front() == std::string(
"Type: d")) {
532 std::string alienSearchCommand = std::string(
"alien.py find ") +
535 auto universe_vector = executeCommand(alienSearchCommand);
537 if (!checkFileUniverse(universe_vector)) {
540 for (
auto&
f : universe_vector) {
544 return universe_vector;
546 LOG(error) <<
"Unsupported file type";
552 auto is_actual_file = std::filesystem::is_regular_file(
path);
553 if (is_actual_file) {
555 if (checkFileName(
path)) {
556 TFile rootfile(
path.c_str(),
"OPEN");
557 if (!rootfile.IsZombie()) {
563 auto files = readLines(
path);
564 if (checkFileUniverse(files)) {
572 auto is_dir = std::filesystem::is_directory(
path);
576 auto files = getLocalFileList(
path);
577 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)
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
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()))