Skip to content
Snippets Groups Projects
Geant4UIManager.cpp 8.11 KiB
Newer Older
//==========================================================================
Markus Frank's avatar
Markus Frank committed
//  AIDA Detector description implementation 
//--------------------------------------------------------------------------
Markus Frank's avatar
Markus Frank committed
// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
Markus Frank's avatar
Markus Frank committed
//
// For the licensing terms see $DD4hepINSTALL/LICENSE.
// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
Markus Frank's avatar
Markus Frank committed
//
// Author     : M.Frank
//
//==========================================================================
Markus Frank's avatar
Markus Frank committed

/// Framework include files
#include <DDG4/Geant4UIManager.h>
#include <DDG4/Geant4Kernel.h>
#include <DDG4/Geant4UIMessenger.h>
#include <DD4hep/Primitives.h>

/// Geant4 include files
#include <G4Version.hh>
#include <G4VisExecutive.hh>
#include <G4UImanager.hh>
#include <G4UIsession.hh>
#include <G4VisExecutive.hh>
#include <G4UIExecutive.hh>
#include <G4RunManager.hh>

/// C/C++ include files
Markus Frank's avatar
Markus Frank committed
using namespace dd4hep::sim;
Markus Frank's avatar
Markus Frank committed
using namespace std;

namespace   {
  string make_cmd(const string& cmd)  {
    return string( "/control/execute "+cmd);
  }
}

Markus Frank's avatar
Markus Frank committed
/// Initializing constructor
Geant4UIManager::Geant4UIManager(Geant4Context* ctxt, const string& nam)
  : Geant4Action(ctxt,nam), m_vis(0), m_ui(0)
Markus Frank's avatar
Markus Frank committed
{
  declareProperty("SetupUI",            m_uiSetup="");
  declareProperty("SetupVIS",           m_visSetup="");
  declareProperty("SessionType",        m_sessionType="tcsh");
  declareProperty("Macros",             m_macros);
  declareProperty("ConfigureCommands",  m_configureCommands);
  declareProperty("InitializeCommands", m_initializeCommands);
  declareProperty("TerminateCommands",  m_terminateCommands);
  declareProperty("Commands",           m_preRunCommands);
  declareProperty("PreRunCommands",     m_preRunCommands);
  declareProperty("PostRunCommands",    m_postRunCommands);
  declareProperty("HaveVIS",            m_haveVis=false);
  declareProperty("HaveUI",             m_haveUI=true);
  declareProperty("Prompt",             m_prompt);
  context()->kernel().register_configure(bind(&Geant4UIManager::configure,this));
  context()->kernel().register_initialize(bind(&Geant4UIManager::initialize,this));
  context()->kernel().register_terminate(bind(&Geant4UIManager::terminate,this));
Markus Frank's avatar
Markus Frank committed
}

/// Default destructor
Geant4UIManager::~Geant4UIManager()   {
}

/// Configure the object
void Geant4UIManager::configure()   {
  /// Get the pointer to the User Interface manager
  G4UImanager* mgr = G4UImanager::GetUIpointer();
  /// Start UI instance
  if ( m_haveUI ) {
    m_ui = startUI();
  }
  /// Execute the chained command statements
  for(const auto& c : m_configureCommands)  {
    info("++ Executing configure command: %s",c.c_str());
    G4int ret = mgr->ApplyCommand(c.c_str());
    if ( ret != 0 )  {
      except("Failed to execute command: %s",c.c_str());
    }
  }
}

/// Initialize the object
void Geant4UIManager::initialize()   {
  /// Get the pointer to the User Interface manager
  G4UImanager* mgr = G4UImanager::GetUIpointer();
  /// Execute the chained command statements
  for(const auto& c : m_initializeCommands)  {
    info("++ Executing initialization command: %s",c.c_str());
    G4int ret = mgr->ApplyCommand(c.c_str());
    if ( ret != 0 )  {
      except("Failed to execute command: %s",c.c_str());
    }
  }
}

/// Callback on terminate
void Geant4UIManager::terminate() {
  /// Get the pointer to the User Interface manager
  G4UImanager* mgr = G4UImanager::GetUIpointer();
  /// Execute the chained command statements
  for(const auto& c : m_terminateCommands)  {
    info("++ Executing finalization command: %s",c.c_str());
    G4int ret = mgr->ApplyCommand(c.c_str());
    if ( ret != 0 )  {
      except("Failed to execute command: %s",c.c_str());
    }
  }
}

/// Apply single command
void Geant4UIManager::applyCommand(const string& command)   {
  /// Get the pointer to the User Interface manager
  G4UImanager* mgr = G4UImanager::GetUIpointer();
  if ( mgr )    {
    info("++ Executing G4 command: %s",command.c_str());
    G4int ret = mgr->ApplyCommand(command.c_str());
    if ( ret == 0 )  {
      return;
    }
    except("Failed to execute command: %s",command.c_str());
  }
  except("No UI reference present. Too early to interact with Geant4!");
}

/// Install command control messenger to write GDML file from command prompt.
void Geant4UIManager::installCommandMessenger()   {
  m_control->addCall("exit", "Force exiting this process",
                     Callback(this).make(&Geant4UIManager::forceExit),0);
  m_control->addCall("terminate", "Regular exit this process",
                     Callback(this).make(&Geant4UIManager::regularExit),0);
}

/// Force exiting this process without calling atexit handlers
void Geant4UIManager::forceExit()   {
  std::_Exit(0);
}

/// Regularly exiting this process without calling atexit handlers
void Geant4UIManager::regularExit()   {
  info("++ End of processing requested.");
  context()->kernel().terminate();
  forceExit();
Markus Frank's avatar
Markus Frank committed
/// Start visualization
G4VisManager* Geant4UIManager::startVis()  {
  /// Initialize visualization
  info("+++ Starting G4VisExecutive ....");
Markus Frank's avatar
Markus Frank committed
  G4VisManager* vis = new G4VisExecutive();
  vis->Initialize();
  return vis;
}

/// Start UI
G4UIExecutive* Geant4UIManager::startUI()   {
  G4UIExecutive* ui = 0;
  const char* args[] = {"DDG4","",""};
  info("+++ Starting G4UIExecutive '%s' of type %s....", args[0], m_sessionType.c_str());
#if (G4VERSION_NUMBER >= 960)
  ui = new G4UIExecutive(1,(char**)args,m_sessionType.c_str());
#else
  ui = new G4UIExecutive(1,(char**)args );
#endif
  if ( !m_prompt.empty() )  {
    ui->SetPrompt(m_prompt);
  }
Markus Frank's avatar
Markus Frank committed
  return ui;
}

/// Run UI
void Geant4UIManager::operator()(void* )   {
  start();
  stop();
}

/// Start manager & session
void Geant4UIManager::start() {
  /// Get the pointer to the User Interface manager
Markus Frank's avatar
Markus Frank committed
  G4UImanager* mgr = G4UImanager::GetUIpointer();
  bool executed_statements = false;
Markus Frank's avatar
Markus Frank committed
  if ( m_haveVis || !m_visSetup.empty() ) {
    m_vis = startVis();
    m_haveVis = true;   /// If graphics setup, vis is always true
    m_haveUI = true;    /// No graphics without UI!
Markus Frank's avatar
Markus Frank committed
  }
Markus Frank's avatar
Markus Frank committed
  if ( !m_visSetup.empty() ) {
    info("++ Executing visualization setup: %s",m_visSetup.c_str());
    mgr->ApplyCommand(make_cmd(m_visSetup).c_str());
Markus Frank's avatar
Markus Frank committed
  }
Markus Frank's avatar
Markus Frank committed
  if ( !m_uiSetup.empty() )   {
    info("++ Executing UI setup: %s",m_uiSetup.c_str());
    mgr->ApplyCommand(make_cmd(m_uiSetup).c_str());
    executed_statements = true;
  }
    info("++ Executing Macro file: %s",m.c_str());
  /// Execute the chained pre-run command statements
  for(const auto& c : m_preRunCommands)  {
    info("++ Executing pre-run statement: %s",c.c_str());
Markus Frank's avatar
Markus Frank committed
  }
  if ( m_haveUI && m_ui )   {
Markus Frank's avatar
Markus Frank committed
    m_ui->SessionStart();
    /// Execute the chained post-run command statements
    for(const auto& c : m_postRunCommands)  {
      info("++ Executing post-run statement: %s",c.c_str());
      mgr->ApplyCommand(c.c_str());
      executed_statements = true;
    }
Markus Frank's avatar
Markus Frank committed
    return;
  }
    return;
  }
  else if ( executed_statements )  {
    /// Execute the chained post-run command statements
    for(const auto& c : m_postRunCommands)  {
      info("++ Executing post-run statement: %s",c.c_str());
  /// No UI. Pure batch mode: Simply execute requested number of events
Markus Frank's avatar
Markus Frank committed
  long numEvent = context()->kernel().property("NumEvents").value<long>();
  if(numEvent < 0) numEvent = numeric_limits<int>::max();
  info("++ Start run with %d events.",numEvent);
  try {
    context()->kernel().runManager().BeamOn(numEvent);
  } catch (DD4hep_End_Of_File& e) {
    context()->kernel().runManager().RunTermination();
Markus Frank's avatar
Markus Frank committed
}

/// Stop and release resources
void Geant4UIManager::stop() {
Markus Frank's avatar
Markus Frank committed
  detail::deletePtr(m_vis);
  detail::deletePtr(m_ui);
Markus Frank's avatar
Markus Frank committed
}