1- // Set include paths for ThePEG headers
2- R__ADD_INCLUDE_PATH ($THEPEG_ROOT /include /)
3- R__ADD_INCLUDE_PATH ($THEPEG_ROOT /../../GSL /latest /include /)
4- R__ADD_INCLUDE_PATH ($HEPMC3_ROOT /include /)
5- R__ADD_INCLUDE_PATH ($HERWIG_ROOT /include /)
61#define SKIP_HEPMC_CONVERSION 1
72#define HAVE_HEPMC3 1
8- #define ThePEG_DEBUG_LEVEL 1
93
104// O2DPG and ROOT includes
115#include "FairGenerator.h"
126#include "FairPrimaryGenerator.h"
137#include "fairlogger/Logger.h"
14- #include "TRandom3.h"
158#include "TParticle.h"
16- #include "TParticlePDG.h"
17- #include "TDatabasePDG.h"
189#include "TLorentzVector.h"
19- #include "TMath.h"
20- #include < fstream >
2110#include <iostream>
2211#include <vector>
2312#include <string>
24- #include < memory >
25-
26- // Undefine conflicting macros before including ThePEG headers
27- #ifdef B0
28- #undef B0
29- #endif
30- #ifdef B50
31- #undef B50
32- #endif
33- #ifdef B75
34- #undef B75
35- #endif
36- #ifdef B110
37- #undef B110
38- #endif
39- #ifdef B134
40- #undef B134
41- #endif
42- #ifdef B150
43- #undef B150
44- #endif
45- #ifdef B200
46- #undef B200
47- #endif
48- #ifdef B300
49- #undef B300
50- #endif
51- #ifdef B600
52- #undef B600
53- #endif
54- #ifdef B1200
55- #undef B1200
56- #endif
57- #ifdef B1800
58- #undef B1800
59- #endif
60- #ifdef B2400
61- #undef B2400
62- #endif
63- #ifdef B4800
64- #undef B4800
65- #endif
66- #ifdef B9600
67- #undef B9600
68- #endif
69- #ifdef B19200
70- #undef B19200
71- #endif
72- #ifdef B38400
73- #undef B38400
74- #endif
75-
76- // ThePEG and Herwig includes
13+
14+ // ThePEG
7715#include "ThePEG/Repository/EventGenerator.h"
7816#include "ThePEG/EventRecord/Event.h"
7917#include "ThePEG/EventRecord/Particle.h"
8018#include "ThePEG/EventRecord/Step.h"
8119#include "ThePEG/Config/ThePEG.h"
8220#include "ThePEG/PDT/ParticleData.h"
83- #include "ThePEG/Vectors/HepMCConverter.h"
8421#include "ThePEG/Repository/Repository.h"
85- #include "ThePEG/Repository/BaseRepository.h"
86- #include "ThePEG/Utilities/DynamicLoader.h"
87- #include "ThePEG/Persistency/PersistentIStream.h"
8822
89- // Herwig specific includes
23+ // Herwig
9024#include "Herwig/API/HerwigAPI.h"
9125#include "Herwig/API/HerwigUI.h"
9226
93- // Subclass of HerwigUI to provide minimal implementation for our use case
27+ // Subclass of HerwigUI to provide minimal implementation of the abstract class
9428class SimpleHerwigUI : public Herwig ::HerwigUI
9529{
9630public :
9731 SimpleHerwigUI (const std ::string & inFile ,
98- Herwig ::RunMode ::Mode mode = Herwig ::RunMode ::READ )
32+ Herwig ::RunMode ::Mode mode = Herwig ::RunMode ::READ , int seed = 0 )
9933 : m_inFile (inFile ), m_mode (mode ),
100- m_in (inFile ), m_out (std ::cout ), m_err (std ::cerr )
34+ m_in (inFile ), m_out (std ::cout ), m_err (std ::cerr ), mSeed ( seed )
10135 {
10236 if (!m_in )
103- throw std ::runtime_error ("Cannot open Herwig input file: " + inFile );
104- Dirs .reserve (5 );
37+ {
38+ LOG (fatal ) << "Cannot open Herwig input file: " << inFile ;
39+ exit (1 );
40+ }
10541 std ::string hDir = std ::getenv ("HERWIG_ROOT" );
10642 if (!hDir .empty ())
43+ {
10744 Dirs .push_back (hDir + "/share/Herwig" );
45+ }
10846 }
10947
11048 Herwig ::RunMode ::Mode runMode () const override { return m_mode ; }
@@ -132,8 +70,8 @@ public:
13270 return empty ;
13371 }
13472
135- long N () const override { return 10 ; } // number of events
136- int seed () const override { return 1234 ; }
73+ long N () const override { return 1 ; } // number of events
74+ int seed () const override { return mSeed ; }
13775 int jobs () const override { return 1 ; }
13876 unsigned int jobSize () const override { return 1 ; }
13977 unsigned int maxJobs () const override { return 1 ; }
@@ -152,6 +90,7 @@ private:
15290 std ::ostream & m_out ;
15391 std ::ostream & m_err ;
15492 std ::vector < std ::string > Dirs ;
93+ int mSeed = 0 ;
15594};
15695
15796namespace o2
@@ -161,52 +100,51 @@ namespace eventgen
161100
162101/// HERWIG7 event generator using ThePEG interface
163102/// Author: Marco Giacalone (marco.giacalone@cern.ch)
164- /// Based on the O2DPG external generator patterns
103+ /// Based on the O2DPG external generator configurations
165104class GeneratorHerwig : public Generator
166105{
167106public :
168107 /// Default constructor
169- GeneratorHerwig (const std ::string & configFile = "LHC.in" )
108+ GeneratorHerwig (const std ::string & configFile = "LHC.in" , int seed = -1 )
170109 : mConfigFile (configFile )
171110 , mEventGenerator (nullptr )
172111 {
173- LOG (info ) << "HERWIG7 Generator initialized " ;
112+ LOG (info ) << "HERWIG7 Generator construction " ;
174113 LOG (info ) << "Config file: " << mConfigFile ;
175114 std ::string extension = mConfigFile .substr (mConfigFile .find_last_of ("." ));
176115 if ( extension == ".in" ) {
177116 mIsInputFile = true;
178117 LOG (info ) << "Using input file for configuration" ;
179- } else if (std :: find ( mConfigFile . end () - 4 , mConfigFile . end (), '.run' ) != mConfigFile . end () ) {
118+ } else if (extension == ".run" ) {
180119 mIsInputFile = false;
181120 LOG (info ) << "Using run file for configuration" ;
182121 } else {
183122 LOG (fatal ) << "No file extension found in config file: " << mConfigFile ;
184123 exit (1 );
185124 }
125+ if (seed == -1 )
126+ {
127+ auto & conf = o2 ::conf ::SimConfig ::Instance ();
128+ mSeed = gRandom -> Integer (conf .getStartSeed ());
129+ } else {
130+ mSeed = seed ;
131+ }
132+ LOG (info ) << "Using seed: " << mSeed << " for HERWIG simulation" ;
186133 }
187134
188135 /// Destructor
189- ~GeneratorHerwig (){
190- delete mEventGenerator ;
191- };
136+ ~GeneratorHerwig () = default ;
192137
193138 /// Initialize the generator
194139 Bool_t Init () override
195140 {
196141 LOG (info ) << "Initializing HERWIG7 Generator" ;
197-
198- try {
199- if (mIsInputFile ) {
200- // Process .in file
201- return initFromInputFile ();
202- } else {
203- // Process .run file directly
204- return initFromRunFile ();
205- }
206-
207- } catch (const std ::exception & e ) {
208- LOG (fatal ) << "Exception during HERWIG7 initialization: " << e .what ();
209- return kFALSE ;
142+ if (mIsInputFile ) {
143+ // Process .in file
144+ return initFromInputFile ();
145+ } else {
146+ // Process .run file directly
147+ return initFromRunFile ();
210148 }
211149 }
212150
@@ -217,28 +155,23 @@ public:
217155 LOG (error ) << "Event generator not initialized" ;
218156 return kFALSE ;
219157 }
220- try {
221- // Clear previous event particles
222- hParticles .clear ();
223-
224- // Generate the event
225- ThePEG ::EventPtr event = mEventGenerator -> shoot ();
226-
227- if (!event ) {
228- LOG (error ) << "Failed to generate event" ;
229- return kFALSE ;
230- }
231-
232- // Convert ThePEG event to TParticle format
233- convertEvent (event );
234- LOG (debug ) << "Herwig7 generated " << hParticles .size ();
158+ // Clear previous event particles
159+ hParticles .clear ();
235160
236- return kTRUE ;
237-
238- } catch (const std ::exception & e ) {
239- LOG (error ) << "Exception during event generation: " << e .what ();
161+ // Generate the event
162+ mPEGEvent = mEventGenerator -> shoot ();
163+
164+ if (!mPEGEvent )
165+ {
166+ LOG (error ) << "Failed to generate event" ;
240167 return kFALSE ;
241168 }
169+
170+ // Convert ThePEG event to TParticle format
171+ convertEvent (mPEGEvent );
172+ LOG (debug ) << "Herwig7 generated " << hParticles .size () << " particles" ;
173+
174+ return kTRUE ;
242175 }
243176
244177 /// Import particles for transport
@@ -259,9 +192,11 @@ public:
259192
260193private :
261194 std ::string mConfigFile ; ///< HERWIG config file (.in or .run)
262- Bool_t mIsInputFile = false; ///< True for .in files, false for .run files
195+ Bool_t mIsInputFile = false; ///< True for .in files, false for .run files
263196 ThePEG ::EGPtr mEventGenerator ; ///< ThePEG event generator
264197 std ::vector < TParticle > hParticles ; ///< Generated Herwig particles
198+ ThePEG ::EventPtr mPEGEvent ; ///< Pointer to Current event
199+ int mSeed = 0 ; ///< Random seed for Herwig
265200
266201 void printHerwigSearchPaths ()
267202 {
@@ -277,61 +212,48 @@ private:
277212 {
278213 LOG (info ) << "Initializing from .in file: " << mConfigFile ;
279214
280- try {
281- using namespace ThePEG ;
282- SimpleHerwigUI ui (mConfigFile , Herwig ::RunMode ::READ );
283-
284- Herwig ::API ::read (ui );
285- printHerwigSearchPaths ();
286- std ::string runFile = mConfigFile ;
287- size_t pos = runFile .find_last_of ('.' );
288- runFile .replace (pos , 4 , ".run" );
289- mConfigFile = runFile ;
290- LOG (info ) << "Generated run file: " << runFile ;
291- auto res = initFromRunFile ();
292- if (!res ) {
293- LOG (error ) << "Failed to initialize from generated run file" ;
294- return kFALSE ;
295- }
296- return kTRUE ;
297- }
298- catch (const std ::exception & e )
299- {
300- std ::cerr << "Exception: " << e .what () << std ::endl ;
215+ using namespace ThePEG ;
216+ SimpleHerwigUI ui (mConfigFile , Herwig ::RunMode ::READ , mSeed );
217+ Herwig ::API ::read (ui );
218+ // For debugging, print the search paths
219+ // printHerwigSearchPaths();
220+ std ::string runFile = mConfigFile ;
221+ size_t pos = runFile .find_last_of ('.' );
222+ runFile .replace (pos , 4 , ".run" );
223+ mConfigFile = runFile ;
224+ LOG (info ) << "Generated run file: " << runFile ;
225+ auto res = initFromRunFile ();
226+ if (!res ) {
227+ LOG (error ) << "Failed to initialize from generated run file" ;
301228 return kFALSE ;
302229 }
230+ return kTRUE ;
303231 }
304232
305233 /// Initialize from .run file
306234 Bool_t initFromRunFile ()
307235 {
308236 LOG (info ) << "Initializing from .run file: " << mConfigFile ;
309237
310- try {
311- using namespace ThePEG ;
312-
313- if (!std ::ifstream (mConfigFile ))
314- {
315- LOG (info ) << "Run file does not exist: " << mConfigFile ;
316- return kFALSE ;
317- }
318- SimpleHerwigUI runui (mConfigFile , Herwig ::RunMode ::RUN );
319- // Prepare the generator
320- mEventGenerator = Herwig ::API ::prepareRun (runui );
321- if (!mEventGenerator )
322- {
323- std ::cerr << "Error: prepareRun() returned null." << std ::endl ;
324- return kFALSE ;
325- }
326-
327- mEventGenerator -> initialize ();
328- std ::cout << "Herwig generator initialized successfully." << std ::endl ;
329- return kTRUE ;
238+ using namespace ThePEG ;
239+
240+ if (!std ::ifstream (mConfigFile ))
241+ {
242+ LOG (info ) << "Run file does not exist: " << mConfigFile ;
243+ return kFALSE ;
330244 }
331- catch (const std ::exception & ex ) {
332- LOG (error ) << "Standard exception: " << ex .what ();
245+ SimpleHerwigUI runui (mConfigFile , Herwig ::RunMode ::RUN , mSeed );
246+ // Prepare the generator
247+ mEventGenerator = Herwig ::API ::prepareRun (runui );
248+ if (!mEventGenerator )
249+ {
250+ LOG (fatal ) << "Error: prepareRun() returned null." ;
333251 return kFALSE ;
334252 }
253+
254+ mEventGenerator -> initialize ();
255+ LOG (info ) << "Herwig generator initialized successfully." ;
256+ return kTRUE ;
335257 }
336258
337259 /// Convert ThePEG event to TParticle format
@@ -396,10 +318,10 @@ private:
396318} // namespace eventgen
397319} // namespace o2
398320
399- /// Factory function to create HERWIG7 generator from .in file
400- /// @param inputFile HERWIG input/run file (e.g., "LHC.in"/"LHC.run")
401- FairGenerator * generateHerwig7 (const std ::string & inputFile = "LHC.in" )
321+ /// HERWIG7 generator from .in/.run file. If seed is -1, a random seed is chosen
322+ /// based on the SimConfig starting seed.
323+ FairGenerator * generateHerwig7 (const std ::string & inputFile = "LHC.in" , int seed = -1 )
402324{
403- auto generator = new o2 ::eventgen ::GeneratorHerwig (inputFile );
325+ auto generator = new o2 ::eventgen ::GeneratorHerwig (inputFile , seed );
404326 return generator ;
405327}
0 commit comments