Skip to content
Snippets Groups Projects
dddigi.py 12.3 KiB
Newer Older
Marko Petric's avatar
Marko Petric committed
# ==========================================================================
Marko Petric's avatar
Marko Petric committed
#  AIDA Detector description implementation
Marko Petric's avatar
Marko Petric committed
# --------------------------------------------------------------------------
# Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
# All rights reserved.
#
# For the licensing terms see $DD4hepINSTALL/LICENSE.
# For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
#
Marko Petric's avatar
Marko Petric committed
# ==========================================================================
from __future__ import absolute_import, unicode_literals
MarkusFrankATcernch's avatar
MarkusFrankATcernch committed
from dd4hep_base import *  # noqa: F401, F403
Markus Frank's avatar
Markus Frank committed
logger = None
Marko Petric's avatar
Marko Petric committed

Markus Frank's avatar
Markus Frank committed
  global logger
Marko Petric's avatar
Marko Petric committed
  import ROOT
Markus Frank's avatar
Markus Frank committed
  import dd4hep_base
Markus Frank's avatar
Markus Frank committed
  logger = dd4hep_base.dd4hep_logger('dddigi')

Marko Petric's avatar
Marko Petric committed
  # Try to load libglapi to avoid issues with TLS Static
  # Turn off all errors from ROOT about the library missing
  if('libglapi' not in gSystem.GetLibraries()):
    orgLevel = ROOT.gErrorIgnoreLevel
    ROOT.gErrorIgnoreLevel = 6000
    gSystem.Load("libglapi")
    ROOT.gErrorIgnoreLevel = orgLevel
  import platform
Marko Petric's avatar
Marko Petric committed
  if platform.system() == "Darwin":
    gSystem.SetDynamicPath(os.environ['DD4HEP_LIBRARY_PATH'])
  #
  # load with ROOT the DDDigi plugin library, which in turn loads the DDigi module
  result = gSystem.Load("libDDDigiPlugins")
  if result < 0:
Marko Petric's avatar
Marko Petric committed
    raise Exception('DDDigi.py: Failed to load the DDDigi library libDDDigiPlugins: ' + gSystem.GetErrorStr())
  logger.info('DDDigi.py: Successfully loaded DDDigi plugin library libDDDigiPlugins!')
  #
  # import with ROOT the I/O module to read DDG4 output
  result = gSystem.Load("libDDDigi_DDG4_IO")
  if result < 0:
    raise Exception('DDDigi.py: Failed to load the DDG4 IO library libDDDigi_DDG4_IO: ' + gSystem.GetErrorStr())
  logger.info('DDDigi.py: Successfully loaded DDG4 IO plugin library libDDDigi_DDG4_IO!')
  #
  # import the main dd4hep module from ROOT
  from ROOT import dd4hep as module
  return module

# We are nearly there ....
current = __import__(__name__)
Marko Petric's avatar
Marko Petric committed

Marko Petric's avatar
Marko Petric committed
def _import_class(ns, nam):
  scope = getattr(current, ns)
  setattr(current, nam, getattr(scope, nam))

Marko Petric's avatar
Marko Petric committed
# ---------------------------------------------------------------------------
Marko Petric's avatar
Marko Petric committed
  dd4hep = loadDDDigi()
  logger.error('+--%-100s--+' % (100 * '-',))
  logger.error('|  %-100s  |' % ('Failed to load DDDigi library:',))
  logger.error('|  %-100s  |' % (str(X),))
  logger.error('+--%-100s--+' % (100 * '-',))
Marko Petric's avatar
Marko Petric committed
core = dd4hep
digi = dd4hep.digi
Kernel = digi.KernelHandle
Interface = digi.DigiActionCreation
Markus Frank's avatar
Markus Frank committed
Detector = core.Detector


Marko Petric's avatar
Marko Petric committed
# ---------------------------------------------------------------------------
Marko Petric's avatar
Marko Petric committed
def _constant(self, name):
  return self.constantAsString(name)

Marko Petric's avatar
Marko Petric committed
# ---------------------------------------------------------------------------
Marko Petric's avatar
Marko Petric committed
def importConstants(description, namespace=None, debug=False):
Markus Frank's avatar
Markus Frank committed
  """
  Import the Detector constants into the dddigi namespace
  """
Marko Petric's avatar
Marko Petric committed
  if namespace is not None and not hasattr(current, namespace):
    m = imp.new_module('dddigi.' + namespace)
Marko Petric's avatar
Marko Petric committed
    setattr(current, namespace, m)
    ns = m
  evaluator = dd4hep.g4Evaluator()
  cnt = 0
  num = 0
  todo = {}
  strings = {}
  for c in description.constants():
    if c.second.dataType == 'string':
      strings[c.first] = c.second.GetTitle()
    else:
Marko Petric's avatar
Marko Petric committed
      todo[c.first] = c.second.GetTitle().replace('(int)', '')
  while len(todo) and cnt < 100:
      logger.info('%s %d out of %d %s "%s": [%s]\n+++ %s' %
                  ('+++ FAILED to import',
                   len(todo), len(todo) + num,
                   'global values into namespace',
                   ns.__name__, 'Try to continue anyway', 100 * '=',))
Marko Petric's avatar
Marko Petric committed
      for k, v in todo.items():
        if not hasattr(ns, k):
          logger.info('+++ FAILED to import: "' + k + '" = "' + str(v) + '"')
      logger.info('+++ %s' % (100 * '=',))
Marko Petric's avatar
Marko Petric committed

    for k, v in todo.items():
      if not hasattr(ns, k):
        val = evaluator.evaluate(v)
        status = evaluator.status()
        if status == 0:
Marko Petric's avatar
Marko Petric committed
          evaluator.setVariable(k, val)
          setattr(ns, k, val)
          if debug:
            logger.info('Imported global value: "' + k + '" = "' + str(val) + '" into namespace' + ns.__name__)
Marko Petric's avatar
Marko Petric committed
  if cnt < 100:
    logger.info('+++ Imported %d global values to namespace:%s' % (num, ns.__name__),)
Marko Petric's avatar
Marko Petric committed
# ---------------------------------------------------------------------------
def _getKernelProperty(self, name):
Marko Petric's avatar
Marko Petric committed
  ret = Interface.getPropertyKernel(self.get(), name)
Marko Petric's avatar
Marko Petric committed
  elif hasattr(self.get(), name):
    return getattr(self.get(), name)
  elif hasattr(self, name):
    return getattr(self, name)
  msg = 'DigiKernel::GetProperty [Unhandled]: Cannot access Kernel.' + name
Marko Petric's avatar
Marko Petric committed
# ---------------------------------------------------------------------------
def _setKernelProperty(self, name, value):
Marko Petric's avatar
Marko Petric committed
  if Interface.setPropertyKernel(self.get(), str(name), str(value)):
Marko Petric's avatar
Marko Petric committed
  msg = 'DigiKernel::SetProperty [Unhandled]: Cannot set Kernel.' + name + ' = ' + str(value)
# ---------------------------------------------------------------------------
def _adopt_property(self, action, foreign_name, local_name):
  Interface.adoptProperty(self.get(), action, str(foreign_name), str(local_name))


# ---------------------------------------------------------------------------
def _add_property(self, name, value):
  Interface.addProperty(self.get(), str(name), value)


# ---------------------------------------------------------------------------
def _add_position_property(self, name, value):
  Interface.addPositionProperty(self.get(), str(name), str(value))


# ---------------------------------------------------------------------------
def _add_set_property(self, name, value):
  Interface.addSetProperty(self.get(), str(name), value)


# ---------------------------------------------------------------------------
def _add_list_property(self, name, value):
  Interface.addListProperty(self.get(), str(name), value)


# ---------------------------------------------------------------------------
def _add_vector_property(self, name, value):
  Interface.addVectorProperty(self.get(), str(name), value)


# ---------------------------------------------------------------------------
def _add_mapped_property(self, name, value):
  Interface.addMappedProperty(self.get(), str(name), value)


Marko Petric's avatar
Marko Petric committed
# ---------------------------------------------------------------------------
Marko Petric's avatar
Marko Petric committed
def _kernel_terminate(self):
  return self.get().terminate()
Marko Petric's avatar
Marko Petric committed
# ---------------------------------------------------------------------------
Kernel.__getattr__ = _getKernelProperty
Kernel.__setattr__ = _setKernelProperty
Marko Petric's avatar
Marko Petric committed
Kernel.terminate = _kernel_terminate
Marko Petric's avatar
Marko Petric committed
# ---------------------------------------------------------------------------
ActionHandle = digi.ActionHandle
ActionHandle.adopt_property = _adopt_property
ActionHandle.add_property = _add_property
ActionHandle.add_position_property = _add_position_property
ActionHandle.add_set_property = _add_set_property
ActionHandle.add_list_property = _add_list_property
ActionHandle.add_vector_property = _add_vector_property
ActionHandle.add_mapped_property = _add_mapped_property
# ---------------------------------------------------------------------------

def _get_action(self):
  if hasattr(self, 'I_am_a_ROOT_interface_handle'):
    return Interface.toAction(self.get())
  return self
Marko Petric's avatar
Marko Petric committed
# ---------------------------------------------------------------------------


def _get_container_action(self):
  if hasattr(self, 'I_am_a_ROOT_interface_handle'):
    return Interface.toContainerAction(self.get())
  return self
# ---------------------------------------------------------------------------


def TestAction(kernel, nam, sleep=0):
  obj = Interface.createAction(kernel, str('DigiTestAction/' + nam))
  if sleep != 0:
    obj.sleep = sleep
# ---------------------------------------------------------------------------
def Action(kernel, nam, **options):
  action = Interface.createAction(kernel, str(nam))
  for option in options.items():
    setattr(action, option[0], option[1])
  return action
Markus Frank's avatar
Markus Frank committed
# ---------------------------------------------------------------------------
Markus Frank's avatar
Markus Frank committed
def _default_adopt(self, action):
  getattr(self, '__adopt')(action.get())
# ---------------------------------------------------------------------------

Markus Frank's avatar
Markus Frank committed
def _adopt_event_action(self, action):
  " Helper to convert DigiActions objects to DigiEventAction "
  getattr(self, '__adopt')(Interface.toEventAction(action.get()))
Marko Petric's avatar
Marko Petric committed
# ---------------------------------------------------------------------------
Markus Frank's avatar
Markus Frank committed
def _adopt_processor_action(self, action, container):
  " Helper to convert DigiActions objects to DigiEventAction "
  attr = getattr(self, 'adopt_processor')
  proc = _get_container_action(self)
  attr(proc, container)
  # print('ContainerProcessor succesfully adopted')
Marko Petric's avatar
Marko Petric committed
# ---------------------------------------------------------------------------
Markus Frank's avatar
Markus Frank committed
def _adopt_sequence_action(self, name, **options):
  " Helper to adopt DigiAction objects for DigiSynchronize "
  kernel = Interface.createKernel(Interface.toAction(self))
  action = Action(kernel, name)
  for option in options.items():
    setattr(action, option[0], option[1])
  self.adopt(action)
  return action
Marko Petric's avatar
Marko Petric committed
# ---------------------------------------------------------------------------
Markus Frank's avatar
Markus Frank committed
def _adopt_processor(self, action, containers):
  getattr(self, '__adopt_processor')(action.get(), containers)
# ---------------------------------------------------------------------------
def _setup(obj, call='adopt', py_call=_default_adopt):
Marko Petric's avatar
Marko Petric committed
  _import_class('digi', obj)
  cls = getattr(current, obj)
Markus Frank's avatar
Markus Frank committed
  setattr(cls, '__' + call, getattr(cls, call))
  setattr(cls, call, py_call)
Markus Frank's avatar
Markus Frank committed
# ---------------------------------------------------------------------------
def _get(self, name):
  a = Interface.toAction(self)
Marko Petric's avatar
Marko Petric committed
  ret = Interface.getProperty(a, name)
Marko Petric's avatar
Marko Petric committed
  elif hasattr(self.action, name):
    return getattr(self.action, name)
Markus Frank's avatar
Markus Frank committed
  elif a.__class__ != self.__class__ and hasattr(a, name):
Marko Petric's avatar
Marko Petric committed
    return getattr(a, name)
  msg = 'DDDigiAction::GetProperty [Unhandled]: Cannot access property ' + a.name() + '.' + name
Markus Frank's avatar
Markus Frank committed
# ---------------------------------------------------------------------------
  """This function is called when properties are passed to the c++ objects."""
Markus Frank's avatar
Markus Frank committed
  import dd4hep as dd4hep
Markus Frank's avatar
Markus Frank committed
  name = dd4hep.unicode_2_string(name)
  value = dd4hep.unicode_2_string(value)
  if Interface.setProperty(a, name, value):
  msg = 'DDDigiAction::SetProperty [Unhandled]: Cannot set ' + a.name() + '.' + name + ' = ' + value
Markus Frank's avatar
Markus Frank committed
# ---------------------------------------------------------------------------
def _props(obj, **extensions):
Marko Petric's avatar
Marko Petric committed
  _import_class('digi', obj)
  cls = getattr(current, obj)
  for extension in extensions.items():
    setattr(cls, extension[0], extension[1])
  cls.__getattr__ = _get
  cls.__setattr__ = _set
  return cls
Markus Frank's avatar
Markus Frank committed
# ---------------------------------------------------------------------------


def _props2(obj, **extensions):
  cls = getattr(current, obj)
  for extension in extensions.items():
    setattr(cls, extension[0], extension[1])
  cls.__getattr__ = _get
  cls.__setattr__ = _set
  return cls
# ---------------------------------------------------------------------------
_setup('DigiSynchronize', call='adopt', py_call=_adopt_event_action)
_setup('DigiActionSequence', call='adopt', py_call=_adopt_event_action)

_import_class('digi', 'DigiKernel')
_import_class('digi', 'DigiContext')
_import_class('digi', 'DigiAction')
_import_class('digi', 'DigiEventAction')
_import_class('digi', 'DigiInputAction')
Markus Frank's avatar
Markus Frank committed
_props('DigiSynchronize', adopt_action=_adopt_sequence_action)
_props('DigiActionSequence', adopt_action=_adopt_sequence_action)
_props('DigiParallelActionSequence', adopt_action=_adopt_sequence_action)
_props('DigiSequentialActionSequence', adopt_action=_adopt_sequence_action)
_props('DigiContainerSequenceAction', adopt_container_processor=_adopt_processor_action)
_setup('DigiMultiContainerProcessor', call='adopt_processor', py_call=_adopt_processor)


Markus Frank's avatar
Markus Frank committed
# Need to import digitize late, since it cross includes dddigi
Digitize = None
try:
  import digitize
  Digitize = digitize.Digitize
except Exception as X:
Markus Frank's avatar
Markus Frank committed
  logger.error('Failed to import digitize: ' + str(X))