diff --git a/DDG4/examples/CLICSidSimuMarkus.py b/DDG4/examples/CLICSidSimuMarkus.py index 05ce087d7afd9c748d473794d24606326b6a1927..e948d9500d31d45ba4a66afe2c7d2fa847f97e81 100644 --- a/DDG4/examples/CLICSidSimuMarkus.py +++ b/DDG4/examples/CLICSidSimuMarkus.py @@ -46,7 +46,7 @@ def run(): geant4 = DDG4.Geant4(kernel,tracker='Geant4TrackerCombineAction') geant4.printDetectors() # Configure UI - geant4.setupCshUI() + geant4.setupCshUI(macro='run.mac',ui=None) field = geant4.addConfig('Geant4FieldTrackingSetupAction/MagFieldTrackingSetup') field.stepper = "HelixSimpleRunge" diff --git a/DDG4/include/DDG4/Geant4UIManager.h b/DDG4/include/DDG4/Geant4UIManager.h index 6f088e48be984538c4e47b10ce4068097a82589c..a7b42e1fb4e376368edc6dbfc60895d81259ddf2 100644 --- a/DDG4/include/DDG4/Geant4UIManager.h +++ b/DDG4/include/DDG4/Geant4UIManager.h @@ -33,6 +33,16 @@ namespace DD4hep { * prompt. To export properties from any action, call the {\tt{enableUI()}} * method of the action. * + * Please note: + * + * Any type of commands may be put together, but the overall execution order + * is as follows: + * 1) Execution of the visualization setup (Property: SetupVIS) + * 2) Execution of the user interface setup (Property: SetupUI) + * 3) Execution of the macro file list (Property: Macros) + * 4) Execution of the command list (Property: Commands) + * + * * \author M.Frank * \version 1.0 */ @@ -44,6 +54,12 @@ namespace DD4hep { std::string m_uiSetup; /// Property: Name of the visualization macro file std::string m_visSetup; + /// Property: Array of macro files to be chained + std::vector<std::string> m_commands; + /// Property: Array of commands to be chained + std::vector<std::string> m_macros; + /// Property: New prompt if the user wants to change it. (Default is do nothing) + std::string m_prompt; /// Property: Flag to instantiate Vis manager (default=false, unless m_visSetup set) bool m_haveVis; /// Property: Flag to instantiate UI (default=true) diff --git a/DDG4/python/DDG4.py b/DDG4/python/DDG4.py index dbc9890ab21e97cd1bd48e43faa22e3c6c31a70f..db6f79114cebc86a0e5f007b5cb472879173c48c 100644 --- a/DDG4/python/DDG4.py +++ b/DDG4/python/DDG4.py @@ -242,11 +242,16 @@ _props('SensDetActionSequenceHandle') _props('Geant4PhysicsListActionSequence') """ -Helper object to perform stuff, which occurs very often. -I am sick of typing the same over and over again. + Helper object to perform stuff, which occurs very often. + I am sick of typing the same over and over again. + Hence, I grouped often used python fragments to this small + class to re-usage. -\author M.Frank -\version 1.0 + Long live laziness! + + + \author M.Frank + \version 1.0 """ class Simple: @@ -261,6 +266,37 @@ class Simple: self.sensitive_types['tracker'] = tracker self.sensitive_types['calorimeter'] = calo + """ + Configure the Geant4 command executive + + \author M.Frank + """ + def setupUI(self,typ='csh',vis=False,ui=True,macro=None): + # Configure UI + ui_action = Action(self.kernel,"Geant4UIManager/UI") + if vis: ui_action.HaveVIS = True + else: ui_action.HaveVIS = False + if ui: ui_action.HaveUI = True + else: ui_action.HaveUI = False + ui_action.SessionType = typ + if macro: + ui_action.SetupUI = macro + self.kernel.registerGlobalAction(ui_action) + return ui_action + + """ + Configure the Geant4 command executive with a csh like command prompt + + \author M.Frank + """ + def setupCshUI(self,typ='csh',vis=False,ui=True,macro=None): + return self.setupUI(typ='csh',vis=vis,ui=ui,macro=macro) + + """ + Add a new phase action to an arbitrary step. + + \author M.Frank + """ def addPhaseAction(self,phase_name,factory_specification,ui=True): action = PhaseAction(self.kernel,factory_specification) self.kernel.phase('configure').add(action) @@ -268,53 +304,53 @@ class Simple: return action """ - Add a new phase action to the 'configure' step. - Called at the beginning of Geant4Exec::configure. - The factory specification is the typical string "<factory_name>/<instance name>". - If no instance name is specified it defaults to the factory name. + Add a new phase action to the 'configure' step. + Called at the beginning of Geant4Exec::configure. + The factory specification is the typical string "<factory_name>/<instance name>". + If no instance name is specified it defaults to the factory name. - \author M.Frank + \author M.Frank """ def addConfig(self, factory_specification): return self.addPhaseAction('configure',factory_specification) """ - Add a new phase action to the 'initialize' step. - Called at the beginning of Geant4Exec::initialize. - The factory specification is the typical string "<factory_name>/<instance name>". - If no instance name is specified it defaults to the factory name. + Add a new phase action to the 'initialize' step. + Called at the beginning of Geant4Exec::initialize. + The factory specification is the typical string "<factory_name>/<instance name>". + If no instance name is specified it defaults to the factory name. - \author M.Frank + \author M.Frank """ def addInit(self, factory_specification): return self.addPhaseAction('initialize',factory_specification) """ - Add a new phase action to the 'start' step. - Called at the beginning of Geant4Exec::run. - The factory specification is the typical string "<factory_name>/<instance name>". - If no instance name is specified it defaults to the factory name. + Add a new phase action to the 'start' step. + Called at the beginning of Geant4Exec::run. + The factory specification is the typical string "<factory_name>/<instance name>". + If no instance name is specified it defaults to the factory name. - \author M.Frank + \author M.Frank """ def addStart(self, factory_specification): return self.addPhaseAction('start',factory_specification) """ - Add a new phase action to the 'stop' step. - Called at the end of Geant4Exec::run. - The factory specification is the typical string "<factory_name>/<instance name>". - If no instance name is specified it defaults to the factory name. + Add a new phase action to the 'stop' step. + Called at the end of Geant4Exec::run. + The factory specification is the typical string "<factory_name>/<instance name>". + If no instance name is specified it defaults to the factory name. - \author M.Frank + \author M.Frank """ def addStop(self, factory_specification): return self.addPhaseAction('stop',factory_specification) """ - Execute the geant 4 program with all steps. + Execute the Geant 4 program with all steps. - \author M.Frank + \author M.Frank """ def execute(self): self.kernel.configure() @@ -374,19 +410,11 @@ class Simple: self.kernel.generatorAction().add(gun) return gun - def setupUI(self,typ='csh',vis=False,ui=True,macro=None): - # Configure UI - ui_action = Action(self.kernel,"Geant4UIManager/UI") - ui_action.HaveVIS = vis - ui_action.HaveUI = ui - ui_action.SessionType = typ - if macro is not None: - ui_action.SetupUI = macro - self.kernel.registerGlobalAction(ui_action) - - def setupCshUI(self,typ='csh',vis=False,ui=True,macro=None): - self.setupUI(typ='csh',vis=vis,ui=ui,macro=macro) + """ + Configure ROOT output for the simulated events + \author M.Frank + """ def setupROOTOutput(self,name,output,mc_truth=True): evt_root = EventAction(self.kernel,'Geant4Output2ROOT/'+name) evt_root.HandleMCTruth = mc_truth @@ -396,6 +424,11 @@ class Simple: self.kernel.eventAction().add(evt_root) return evt_root + """ + Configure LCIO output for the simulated events + + \author M.Frank + """ def setupLCIOOutput(self,name,output): evt_lcio = EventAction(self.kernel,'Geant4Output2LCIO/'+name) evt_lcio.Control = True @@ -404,13 +437,28 @@ class Simple: self.kernel.eventAction().add(evt_lcio) return evt_lcio - def buildInputStage(self, generator_input_modules, output_level=None): + """ + Generic build of the input stage with multiple input modules. + + Actions executed are: + 1) Register Generation initialization action + 2) Append all modules to build the complete input record + These modules are readers/particle sources, boosters and/or smearing actions. + 3) Merge all existing interaction records + 4) Add the MC truth handler + + \author M.Frank + """ + def buildInputStage(self, generator_input_modules, output_level=None, have_mctruth=True): ga = self.kernel.generatorAction() + # Register Generation initialization action gen = GeneratorAction(self.kernel,"Geant4GeneratorActionInit/GenerationInit") if output_level is not None: gen.OutputLevel = output_level ga.adopt(gen) + # Now append all modules to build the complete input record + # These modules are readers/particle sources, boosters and/or smearing actions for gen in generator_input_modules: gen.enableUI() if output_level is not None: @@ -425,11 +473,13 @@ class Simple: ga.adopt(gen) # Finally generate Geant4 primaries - gen = GeneratorAction(self.kernel,"Geant4PrimaryHandler/PrimaryHandler") - gen.enableUI() - if output_level is not None: - gen.OutputLevel = output_level - ga.adopt(gen) + if have_mctruth: + gen = GeneratorAction(self.kernel,"Geant4PrimaryHandler/PrimaryHandler") + gen.enableUI() + if output_level is not None: + gen.OutputLevel = output_level + ga.adopt(gen) + # Puuuhh! All done. return self Geant4 = Simple diff --git a/DDG4/src/Geant4UIManager.cpp b/DDG4/src/Geant4UIManager.cpp index 8e3c77f1b659aba60da340f8d7dad8bab2a38e5d..e2e3e24f02243edaa44a584d290f95ddcb4b3457 100644 --- a/DDG4/src/Geant4UIManager.cpp +++ b/DDG4/src/Geant4UIManager.cpp @@ -18,19 +18,27 @@ #include "G4UIExecutive.hh" #include "G4RunManager.hh" - using namespace DD4hep::Simulation; using namespace std; +namespace { + string make_cmd(const string& cmd) { + return string( "/control/execute "+cmd); + } +} + /// Initializing constructor Geant4UIManager::Geant4UIManager(Geant4Context* ctxt, const std::string& nam) : Geant4Action(ctxt,nam), m_vis(0), m_ui(0) { - declareProperty("SetupUI", m_uiSetup=""); - declareProperty("SetupVIS", m_visSetup=""); + declareProperty("SetupUI", m_uiSetup=""); + declareProperty("SetupVIS", m_visSetup=""); declareProperty("SessionType", m_sessionType="tcsh"); - declareProperty("HaveVIS", m_haveVis=false); - declareProperty("HaveUI", m_haveUI=true); + declareProperty("Macros", m_macros); + declareProperty("Commands", m_commands); + declareProperty("HaveVIS", m_haveVis=false); + declareProperty("HaveUI", m_haveUI=true); + declareProperty("Prompt", m_prompt); } /// Default destructor @@ -58,7 +66,9 @@ G4UIExecutive* Geant4UIManager::startUI() { #else ui = new G4UIExecutive(1,(char**)args ); #endif - + if ( !m_prompt.empty() ) { + ui->SetPrompt(m_prompt); + } return ui; } @@ -70,8 +80,10 @@ void Geant4UIManager::operator()(void* ) { /// Start manager & session void Geant4UIManager::start() { + typedef std::vector<std::string> _V; // Get the pointer to the User Interface manager G4UImanager* mgr = G4UImanager::GetUIpointer(); + bool executed_statements = false; // Start visualization if ( m_haveVis || !m_visSetup.empty() ) { @@ -80,27 +92,46 @@ void Geant4UIManager::start() { m_haveUI = true; // No graphics without UI! } // Start UI instance - if ( m_haveUI || !m_uiSetup.empty() ) { + if ( m_haveUI ) { m_ui = startUI(); } // Configure visualization instance if ( !m_visSetup.empty() ) { - string cmd = "/control/execute "+m_visSetup; - mgr->ApplyCommand(cmd.c_str()); - printout(INFO,"Geant4UIManager","++ Executed visualization setup:%s",m_visSetup.c_str()); + printout(INFO,"Geant4UIManager","++ Executing visualization setup:%s",m_visSetup.c_str()); + mgr->ApplyCommand(make_cmd(m_visSetup).c_str()); } // Configure UI instance if ( !m_uiSetup.empty() ) { - string cmd = "/control/execute "+m_uiSetup; - mgr->ApplyCommand(cmd.c_str()); - printout(INFO,"Geant4UIManager","++ Executed UI setup:%s",m_uiSetup.c_str()); + printout(INFO,"Geant4UIManager","++ Executing UI setup:%s",m_uiSetup.c_str()); + mgr->ApplyCommand(make_cmd(m_uiSetup).c_str()); + executed_statements = true; + } + // Execute the chained macro files + for(_V::const_iterator i=m_macros.begin(); i!=m_macros.end(); ++i) { + printout(INFO,"Geant4UIManager","++ Executing Macro file:%s",(*i).c_str()); + mgr->ApplyCommand(make_cmd(*i).c_str()); + executed_statements = true; + } + // Execute the chained command statements + for(_V::const_iterator i=m_commands.begin(); i!=m_commands.end(); ++i) { + printout(INFO,"Geant4UIManager","++ Executing Command statement:%s",(*i).c_str()); + mgr->ApplyCommand((*i).c_str()); + executed_statements = true; } // Start UI session if present if ( m_haveUI && m_ui ) { m_ui->SessionStart(); return; } - // No UI. Simply execute requested number of events + else if ( m_haveUI ) { + printout(WARNING,"Geant4UIManager","++ No UI manager found. Exit."); + return; + } + else if ( executed_statements ) { + return; + } + + // No UI. Pure batch mode: Simply execute requested number of events long numEvent = context()->kernel().property("NumEvents").value<long>(); printout(INFO,"Geant4UIManager","++ Start run with %d events.",numEvent); context()->kernel().runManager().BeamOn(numEvent);