Skip to content
Snippets Groups Projects
Geant4UIMessenger.cpp 5.41 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)
// For the licensing terms see $DD4hepINSTALL/LICENSE.
// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
// Author     : M.Frank
//
//==========================================================================

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

// Geant4 include files
#include <G4UIcmdWithoutParameter.hh>
#include <G4UIcmdWithAString.hh>

// C/C++ include files
#include <algorithm>

Markus Frank's avatar
Markus Frank committed
using namespace dd4hep::sim;

namespace {
  struct InstallProperties {
    Geant4UIMessenger::Commands& cmds;
    const std::string& path;
    G4UImessenger* msg;
    InstallProperties(Geant4UIMessenger::Commands& c, const std::string& p, G4UImessenger* m)
    void operator()(const std::pair<std::string, dd4hep::Property>& o) {
      std::string n = path + o.first;
      G4UIcmdWithAString* cmd = new G4UIcmdWithAString(n.c_str(), msg);
      cmd->SetParameterName(o.first.c_str(), true);
      cmd->SetGuidance(("Property item of type " + o.second.type()).c_str());
      cmds[cmd] = o.first;
    }
  };
}

Geant4UIMessenger::Geant4UIMessenger(const std::string& name, const std::string& path)
  : G4UImessenger(), m_directory(0), m_properties(0), m_name(name), m_path(path) {
  m_directory = new G4UIdirectory(path.c_str());
  printout(INFO, "Geant4UI", "+++ %s> Install Geant4 control directory:%s", name.c_str(), path.c_str());
  m_directory->SetGuidance(("Control hierarchy for Geant4 action:" + name).c_str());
}

/// Default destructor
Geant4UIMessenger::~Geant4UIMessenger() {
Markus Frank's avatar
Markus Frank committed
  detail::destroyFirst(m_propertyCmd);
  detail::destroyFirst(m_actionCmd);
}

/// Add a new callback structure
void Geant4UIMessenger::addCall(const std::string& name, const std::string& description, const Callback& cb, size_t npar) {
  if ( 0 == npar )    {
    G4UIcommand* cmd = new G4UIcmdWithoutParameter((m_path + name).c_str(), this);
    cmd->SetGuidance(description.c_str());
    m_actionCmd[cmd] = cb;
  }
  else if ( 1 == npar )    {
    G4UIcmdWithAString* cmd = new G4UIcmdWithAString((m_path + name).c_str(), this);
    cmd->SetParameterName("p1", true);
    cmd->SetGuidance(description.c_str());
    m_actionCmd[cmd] = cb;
  }
  else    {
    except("Geant4UIMessenger","+++ Currently only callbacks with one argument are handled! [Contact developers if more are required]");
  }
}

/// Export all properties to the Geant4 UI
void Geant4UIMessenger::exportProperties(PropertyManager& mgr) {
  InstallProperties installer(m_propertyCmd, m_path, this);
  m_properties = &mgr;
  addCall("show", "Show all properties of Geant4 component:" + m_name,
          Callback(m_properties).make(&PropertyManager::dump));
  m_properties->for_each(installer);
}

/// Pass current property value to Geant4 UI
G4String Geant4UIMessenger::GetCurrentValue(G4UIcommand * c) {
  Commands::iterator i = m_propertyCmd.find(c);
  if (m_properties && i != m_propertyCmd.end()) {
    const std::string& n = (*i).second;
    return (*m_properties)[n].str();
  }
           "+++ %s> Failed to access property value.", m_name.c_str());
  return "";
}

/// Accept ne property value from Geant4 UI
void Geant4UIMessenger::SetNewValue(G4UIcommand *c, G4String v) {
  Commands::iterator i = m_propertyCmd.find(c);
  if (m_properties && i != m_propertyCmd.end()) {
    const std::string& n = (*i).second;
    try  {
      if (!v.empty()) {
                 "+++ %s> Setting property value %s = %s  native:%s.",
                 m_name.c_str(), n.c_str(), v.c_str(), p.str().c_str());
        std::string value = (*m_properties)[n].str();
        printout(INFO, "Geant4UI", "+++ %s> Unchanged property value %s = %s.",
                 m_name.c_str(), n.c_str(), value.c_str());
    catch(const std::exception& e)   {
      printout(INFO, "Geant4UI", "+++ %s> Exception: Failed to change property %s = '%s'.",
      printout(INFO, "Geant4UI", "+++ %s> Exception: %s", m_name.c_str(), e.what());
      printout(INFO, "Geant4UI", "+++ %s> UNKNOWN Exception: Failed to change property %s = '%s'.",
  else  {
    Actions::iterator j = m_actionCmd.find(c);
    if (j != m_actionCmd.end()) {
      try  {
        const void* args[] = {v.c_str(), 0};
        (*j).second.execute(args);
      catch(const std::exception& e)   {
        printout(INFO, "Geant4UI", "+++ %s> Exception: Failed to exec action '%s' [%s].",
                 m_name.c_str(), c->GetCommandName().c_str(), c->GetCommandPath().c_str());
        printout(INFO, "Geant4UI", "+++ %s> Exception: %s",e.what());
        printout(INFO, "Geant4UI", "+++ %s> UNKNOWN Exception: Failed to exec action '%s' [%s].",
                 m_name.c_str(), c->GetCommandName().c_str(), c->GetCommandPath().c_str());
  printout(INFO, "Geant4UI", "+++ %s> Unknown command callback!", m_name.c_str());