16#include <fairlogger/Logger.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);
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() * 1
e-9;
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 if (!checkFileName(
path)) {
539 auto tmpPath = (std::filesystem::temp_directory_path() / (
"list_" +
std::to_string(getpid()) +
".txt")).string();
540 auto res = TFile::Cp(Form(
"%s?filetype=raw",
path.c_str()), tmpPath.c_str());
542 LOG(fatal) <<
"Failed to copy file from AliEn: " <<
path;
544 auto files = readLines(tmpPath);
545 if (checkFileUniverse(files)) {
548 LOG(fatal) <<
"The list of files in " <<
path <<
" is not valid";
550 std::filesystem::remove(tmpPath);
556 }
else if (typeString.size() == 1 && typeString.front() == std::string(
"Type: d")) {
559 std::string alienSearchCommand = std::string(
"alien.py find ") +
562 auto universe_vector = executeCommand(alienSearchCommand);
564 if (!checkFileUniverse(universe_vector)) {
567 for (
auto&
f : universe_vector) {
571 return universe_vector;
573 LOG(
error) <<
"Unsupported file type";
579 auto is_actual_file = std::filesystem::is_regular_file(
path);
580 if (is_actual_file) {
582 if (checkFileName(
path)) {
583 TFile rootfile(
path.c_str(),
"OPEN");
584 if (!rootfile.IsZombie()) {
590 auto files = readLines(
path);
591 if (checkFileUniverse(files)) {
599 auto is_dir = std::filesystem::is_directory(
path);
603 auto files = getLocalFileList(
path);
604 if (checkFileUniverse(files)) {
configStandalone Light OpenGL display display_light Apply smoothing to points Enable Z buffer Highlight links Highlight seeds Highlight sector tracks Highlight final tracks Show individual Show related Highlight grid Show only individual collision Color clusters belonging to track objects Set line Enable drawing TPC data Enable drawing TOF data Enable drawing magnetic field Set field line step count Invert colors configStandalone Heavy OpenGL display display_heavy Show tracks with ITS contribution Show tracks with TOF contribution Enable propagation of loopers Show clusters at nominal x of pad row for early transformed data Split CE tracks when they cross the central Mark clusters Mark adjacent clusters Hide rejected tracks Apply filter on tracks to be displayed Separate increase X h configStandalone Camera window renderer OpenGL display display_camera Orient the camera such that the y axis is always upwards Full Screen MultiSample Anti Downsampling Anti Enable Vertical Sync Target frame or if the backend cannot limit to the refresh Use OpenGL indirect draws to reduce number of draw calls Display h configStandalone Vulkan display display_vulkan Have uniform buffers in host accessible device memory h configStandalone Internal display display_internal Number of updates the Qt GUI may send ahead of the last one the display has before it waits for the display Opacity of the console background Number of console lines the history is shortened to this when it reaches twice the size Time in seconds an info message fades out after setInfoTime h OpenGL display display Font size Do not use Freetype for font Renderer for event Frontend to use for event ROOT macros used as track filter Console script file
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char e
ClassImp(o2::eventgen::GeneratorFromEventPool)
char error[CURL_ERROR_SIZE]
std::vector< o2::its::TrackITS > tracks
Definition of the MCTrack class.
virtual void AddTrack(Int_t pdgid, Double_t px, Double_t py, Double_t pz, Double_t vx, Double_t vy, Double_t vz, Int_t parent=-1, Bool_t wanttracking=true, Double_t e=-9e9, Double_t tof=0., Double_t weight=0., TMCProcess proc=kPPrimary)
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 int32_t line
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
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()))