1+ #if !defined(__CLING__ ) || defined(__ROOTCLING__ )
2+ #include "FairGenerator.h"
3+ #include "TDatabasePDG.h"
4+ #include "TFile.h"
5+ #include "TMath.h"
6+ #include "TSystem.h"
7+ #include "TTree.h"
8+ #include "SimulationDataFormat/MCTrack.h"
9+ #include <iostream>
10+ #include <vector>
11+ #include <algorithm>
12+ #endif
13+
14+ // Include the underlying rapidity generator header/macro
15+ #include "generator_pythia8_LF_rapidity.C"
16+
17+ /// Entry point to configure the particle gun generator for resonance simulation
18+ FairGenerator * generatePhiResonanceGun (int pdg = 999999 , // Custom PDG or specific target PDG
19+ float ptMin = 0.0 ,
20+ float ptMax = 50.0 ,
21+ float yMin = -1.0 ,
22+ float yMax = 1.0 ,
23+ std ::string pythiaCfg = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg" ,
24+ int nInject = 3 )
25+ {
26+ // Configure particle parameters (PDG, count, ptMin, ptMax, yMin, yMax)
27+ GeneratorPythia8LFRapidity ::ConfigContainer cfg (pdg , nInject , ptMin , ptMax , yMin , yMax );
28+
29+ std ::vector < GeneratorPythia8LFRapidity ::ConfigContainer > cfgVec ;
30+ std ::vector < GeneratorPythia8LFRapidity ::ConfigContainer > cfgVecGenDecayed ;
31+
32+ // Let Pythia generator handle decays internally
33+ cfgVecGenDecayed .push_back (cfg );
34+
35+ return generateLFRapidity (cfgVec , cfgVecGenDecayed ,
36+ /*injectOnePDGPerEvent=*/ true,
37+ /*gapBetweenInjection=*/ 0 ,
38+ /*useTrigger=*/ false,
39+ /*useRapidity=*/ true,
40+ /*pythiaCfgMb=*/ pythiaCfg ,
41+ /*pythiaCfgSignal=*/ "" );
42+ }
43+
44+ /// Validation function to analyze o2sim_Kine.root post-simulation
45+ int External ()
46+ {
47+ std ::string path {"o2sim_Kine.root" };
48+ int numberOfGapEvents {0 };
49+ int numberOfEventsProcessed {0 };
50+ int numberOfEventsProcessedWithoutInjection {0 };
51+
52+ // Target PDG state and decaying daughters (e.g. Phi -> K+ K-)
53+ std ::vector < int > injectedPDGs = {999999 };
54+ std ::vector < std ::vector < int >> decayDaughters = {
55+ {333 , 333 } // Decaying into phi-phi (PDG 333, 333)
56+ };
57+
58+ auto nInjection = injectedPDGs .size ();
59+
60+ TFile file (path .c_str (), "READ ");
61+ if (file .IsZombie ())
62+ {
63+ std ::cerr << "Cannot open ROOT file " << path << "\n" ;
64+ return 1 ;
65+ }
66+
67+ auto tree = (TTree * )file .Get ("o2sim" );
68+ if (!tree )
69+ {
70+ std ::cerr << "Cannot find tree o2sim in file " << path << "\n" ;
71+ return 1 ;
72+ }
73+
74+ std ::vector < o2 ::MCTrack > * tracks {};
75+ tree -> SetBranchAddress ("MCTrack" , & tracks );
76+
77+ std ::vector < int > nSignal (nInjection , 0 );
78+ std ::vector < std ::vector < int >> nDecays ;
79+ std ::vector < int > nNotDecayed (nInjection , 0 );
80+
81+ for (size_t i = 0 ; i < nInjection ; i ++ )
82+ {
83+ nDecays .push_back (std ::vector < int > (decayDaughters [i ].size (), 0 ));
84+ }
85+
86+ auto nEvents = tree -> GetEntries ();
87+ bool hasInjection = false;
88+
89+ for (int i = 0 ; i < nEvents ; i ++ )
90+ {
91+ hasInjection = false;
92+ numberOfEventsProcessed ++ ;
93+ tree -> GetEntry (i );
94+
95+ for (size_t idxMCTrack = 0 ; idxMCTrack < tracks -> size (); ++ idxMCTrack )
96+ {
97+ auto track = tracks -> at (idxMCTrack );
98+ auto pdg = track .GetPdgCode ();
99+ auto it = std ::find (injectedPDGs .begin (), injectedPDGs .end (), pdg );
100+
101+ if (it != injectedPDGs .end ())
102+ {
103+ int index = std ::distance (injectedPDGs .begin (), it );
104+ nSignal [index ]++ ;
105+
106+ if (track .getFirstDaughterTrackId () < 0 )
107+ {
108+ nNotDecayed [index ]++ ;
109+ continue ;
110+ }
111+
112+ for (int j {track .getFirstDaughterTrackId ()}; j <= track .getLastDaughterTrackId (); ++ j )
113+ {
114+ auto pdgDau = tracks -> at (j ).GetPdgCode ();
115+ bool foundDau = false;
116+
117+ for (size_t idxDaughter = 0 ; idxDaughter < decayDaughters [index ].size (); ++ idxDaughter )
118+ {
119+ if (pdgDau == decayDaughters [index ][idxDaughter ])
120+ {
121+ nDecays [index ][idxDaughter ]++ ;
122+ foundDau = true;
123+ hasInjection = true;
124+ break ;
125+ }
126+ }
127+ if (!foundDau )
128+ {
129+ std ::cerr << "Decay daughter not found: " << pdg << " -> " << pdgDau << "\n" ;
130+ }
131+ }
132+ }
133+ }
134+ if (!hasInjection )
135+ {
136+ numberOfEventsProcessedWithoutInjection ++ ;
137+ }
138+ }
139+
140+ std ::cout << "--------------------------------\n" ;
141+ std ::cout << "# Events: " << nEvents << "\n" ;
142+ for (size_t i = 0 ; i < nInjection ; i ++ )
143+ {
144+ std ::cout << "# Mother PDG " << injectedPDGs [i ] << " generated: "
145+ << nSignal [i ] << ", " << nNotDecayed [i ] << " did not decay\n" ;
146+ for (size_t j = 0 ; j < decayDaughters [i ].size (); j ++ )
147+ {
148+ std ::cout << "# Daughter PDG " << decayDaughters [i ][j ] << ": " << nDecays [i ][j ] << "\n" ;
149+ }
150+ }
151+ std ::cout << "--------------------------------\n" ;
152+
153+ return 0 ;
154+ }
155+
156+ void GeneratorLF_phiphi2 () { External (); }
0 commit comments