Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-20 08:24:20

0001 # ==========================================================================
0002 #  AIDA Detector description implementation
0003 # --------------------------------------------------------------------------
0004 # Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 # All rights reserved.
0006 #
0007 # For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 # For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 #
0010 # ==========================================================================
0011 import cppyy
0012 import importlib
0013 import types
0014 import logging
0015 
0016 logger = logging.getLogger(__name__)
0017 
0018 
0019 # ---------------------------------------------------------------------------
0020 def dd4hep_directories(g4=True):
0021   """
0022   Return tuple of relevant dd4hep directories: (dd4hep, rootsys, geant4)
0023   """
0024   import os
0025   dd4hep = os.getenv("DD4hepINSTALL", "/usr")
0026   rootsys = os.getenv("ROOTSYS", "/usr")
0027   g4_dir = None
0028   if g4:
0029     g4_dir = os.getenv('G4INSTALL', "/usr")
0030   return (rootsys, g4_dir, dd4hep, )
0031 
0032 
0033 # ---------------------------------------------------------------------------
0034 def root_add_compile_option(option):
0035   from ROOT import gSystem
0036   known = gSystem.GetIncludePath()
0037   idx = known.find(option + ' ')
0038   if idx > 0 and idx + len(option) >= len(known):
0039     return known
0040   gSystem.AddIncludePath(' ' + option)
0041 
0042 
0043 # ---------------------------------------------------------------------------
0044 def root_add_include_path(path):
0045   from ROOT import gSystem
0046   known = gSystem.GetIncludePath()
0047   path = '"' + path + '"'
0048   idx = known.find(path)
0049   if idx > 0 and idx + len(path) == len(known):
0050     return known
0051   gSystem.AddIncludePath(' -I' + path)
0052 
0053 
0054 # ---------------------------------------------------------------------------
0055 def setup_root_include_path(g4=True, opt=None):
0056   """
0057   Setup the ROOT compile options and include directories
0058   """
0059   from ROOT import gSystem
0060   rootsys, geant4, dd4hep = dd4hep_directories(g4)
0061   known = gSystem.GetIncludePath()
0062 
0063   root_add_include_path(rootsys + '/include')
0064   root_add_include_path(dd4hep + '/include')
0065   if geant4:
0066     root_add_include_path(geant4 + '/include/Geant4')
0067     root_add_compile_option(' -Wno-shadow -g -O0')
0068   if opt and known.find(opt) < 0:
0069     gSystem.AddIncludePath(' ' + opt)
0070   return gSystem.GetIncludePath()
0071 
0072 
0073 # ---------------------------------------------------------------------------
0074 def root_compile_opts():
0075   """
0076   Return the ROOT compile options and include directories
0077   """
0078   from ROOT import gSystem
0079   return gSystem.GetIncludePath()
0080 
0081 
0082 # ---------------------------------------------------------------------------
0083 def setup_root_library_path(g4=True, opt=None):
0084   """
0085   Setup the ROOT link libraries and link options for A-Click processing of dd4hep in ROOT
0086   """
0087   from ROOT import gSystem
0088   rootsys, geant4, dd4hep = dd4hep_directories(g4)
0089   known = gSystem.GetLinkedLibs()
0090 
0091   lib = ' -L' + dd4hep + '/lib64 ' + ' -L' + dd4hep + '/lib -lDDCore -lDDG4 -lDDSegmentation '
0092   if known.find(lib) >= 0:
0093     lib = ''
0094   if geant4:
0095     g4_lib = ' -L' + geant4 + '/lib64  -L' + geant4 + '/lib -lG4event -lG4tracking -lG4particles '
0096     if known.find(g4_lib) < 0:
0097       lib = lib + g4_lib
0098   if opt and known.find(opt) < 0:
0099     lib = lib + ' ' + opt
0100 
0101   if len(lib):
0102     gSystem.AddLinkedLibs(lib)
0103   return gSystem.GetLinkedLibs()
0104 
0105 
0106 # ---------------------------------------------------------------------------
0107 def root_linked_libs():
0108   """
0109   Access the ROOT link libraries and link options for A-Click processing of dd4hep in ROOT
0110   """
0111   from ROOT import gSystem
0112   return gSystem.GetLinkedLibs()
0113 
0114 
0115 # ---------------------------------------------------------------------------
0116 def compileAClick(dictionary, g4=True):
0117   """
0118   We compile the DDG4 plugin on the fly if it does not exist using the AClick mechanism.
0119 
0120   """
0121   from ROOT import gInterpreter
0122   import os.path
0123 
0124   setup_root_include_path(g4)
0125   setup_root_library_path(g4)
0126   logger.info('Loading AClick %s', dictionary)
0127   package_spec = importlib.util.find_spec('DDG4')
0128   dic = os.path.dirname(package_spec.origin) + os.sep + dictionary
0129   gInterpreter.ProcessLine('.L ' + dic + '+')
0130   from ROOT import dd4hep as module
0131   return module
0132 
0133 
0134 # ---------------------------------------------------------------------------
0135 def loaddd4hep():
0136   """
0137   Import DD4hep module from ROOT using ROOT reflection
0138   """
0139   import os
0140   import sys
0141   # Add ROOT to the python path in case it is not yet there....
0142   rootsys = os.getenv("ROOTSYS", "/usr")
0143   sys.path.append(os.path.join(rootsys, 'lib'))
0144   sys.path.append(os.path.join(rootsys, 'lib64'))
0145   sys.path.append(os.path.join(rootsys, 'lib', 'root'))
0146   sys.path.append(os.path.join(rootsys, 'lib64', 'root'))
0147   from ROOT import gSystem
0148 
0149   import platform
0150   if platform.system() == "Darwin":
0151     gSystem.SetDynamicPath(os.environ['DD4HEP_LIBRARY_PATH'])
0152     os.environ['DYLD_LIBRARY_PATH'] = os.pathsep.join([os.environ['DD4HEP_LIBRARY_PATH'],
0153                                                        os.environ.get('DYLD_LIBRARY_PATH', '')]).strip(os.pathsep)
0154   result = gSystem.Load("libDDCore")
0155   if result < 0:
0156     raise Exception('dd4hep.py: Failed to load the dd4hep library libDDCore: ' + gSystem.GetErrorStr())
0157   from ROOT import dd4hep as module
0158   return module
0159 
0160 
0161 # We are nearly there ....
0162 name_space = __import__(__name__)
0163 
0164 
0165 # ---------------------------------------------------------------------------
0166 def import_namespace_item(ns, nam):
0167   scope = getattr(name_space, ns)
0168   attr = getattr(scope, nam)
0169   setattr(name_space, nam, attr)
0170   return attr
0171 
0172 
0173 # ---------------------------------------------------------------------------
0174 def import_root(nam):
0175   setattr(name_space, nam, getattr(ROOT, nam))
0176 
0177 
0178 # ---------------------------------------------------------------------------
0179 #
0180 try:
0181   dd4hep = loaddd4hep()
0182   import ROOT
0183 except Exception as X:
0184   import sys
0185   logger.error('+--%-100s--+', 100 * '-')
0186   logger.error('|  %-100s  |', 'Failed to load dd4hep base library:')
0187   logger.error('|  %-100s  |', str(X))
0188   logger.error('+--%-100s--+', 100 * '-')
0189   sys.exit(1)
0190 
0191 
0192 # ---------------------------------------------------------------------------
0193 class _Levels:
0194   def __init__(self):
0195     self.VERBOSE = 1
0196     self.DEBUG = 2
0197     self.INFO = 3
0198     self.WARNING = 4
0199     self.ERROR = 5
0200     self.FATAL = 6
0201     self.ALWAYS = 7
0202 
0203 
0204 # ---------------------------------------------------------------------------
0205 def unicode_2_string(value):
0206   """Turn any unicode literal into str, needed when passing to c++.
0207 
0208   Recursively transverses dicts, lists, sets, tuples
0209 
0210   :return: always a str
0211   """
0212   if isinstance(value, (bool, float, int)):
0213     value = value
0214   elif isinstance(value, str):
0215     value = str(value)
0216   elif isinstance(value, bytes):
0217     value = value.decode()
0218   elif isinstance(value, (list, set, tuple)):
0219     value = [unicode_2_string(x) for x in value]
0220   elif isinstance(value, dict):
0221     tempDict = {}
0222     for key, val in value.items():
0223       key = unicode_2_string(key)
0224       val = unicode_2_string(val)
0225       tempDict[key] = val
0226     value = tempDict
0227   return str(value)
0228 
0229 
0230 OutputLevel = _Levels()
0231 VERBOSE = OutputLevel.VERBOSE
0232 DEBUG = OutputLevel.DEBUG
0233 INFO = OutputLevel.INFO
0234 WARNING = OutputLevel.WARNING
0235 ERROR = OutputLevel.ERROR
0236 FATAL = OutputLevel.FATAL
0237 
0238 
0239 # ------------------------Generic STL stuff can be accessed using std:  -----
0240 #
0241 # -- e.g. Create an instance of std::vector<dd4hep::sim::Geant4Vertex*>:
0242 #    >>> v=dd4hep.vector('dd4hep::sim::Geant4Vertex*')()
0243 #
0244 # ---------------------------------------------------------------------------
0245 std = cppyy.gbl.std
0246 std_vector = std.vector
0247 std_list = std.list
0248 std_map = std.map
0249 std_pair = std.pair
0250 # ---------------------------------------------------------------------------
0251 core = dd4hep
0252 cond = dd4hep.cond
0253 tools = dd4hep.tools
0254 align = dd4hep.align
0255 detail = dd4hep.detail
0256 units = types.ModuleType('units')
0257 # ---------------------------------------------------------------------------
0258 import_namespace_item('tools', 'Evaluator')
0259 # ---------------------------------------------------------------------------
0260 import_namespace_item('core', 'NamedObject')
0261 import_namespace_item('core', 'run_interpreter')
0262 #
0263 import_namespace_item('detail', 'interp')
0264 # No: This inhibits the usage of native python eval!
0265 # import_namespace_item('detail', 'eval')
0266 
0267 # ---------------------------------------------------------------------------
0268 # def run_interpreter(name):   detail.interp.run(name)
0269 # def evaluator():     return eval.instance()
0270 # def g4Evaluator():   return eval.g4instance()
0271 
0272 
0273 # ---------------------------------------------------------------------------
0274 def import_detail():
0275   import_namespace_item('detail', 'DD4hepUI')
0276 
0277 
0278 # ---------------------------------------------------------------------------
0279 def import_geometry():
0280   import_namespace_item('core', 'setPrintLevel')
0281   import_namespace_item('core', 'setPrintFormat')
0282   import_namespace_item('core', 'printLevel')
0283   import_namespace_item('core', 'PrintLevel')
0284 
0285   import_namespace_item('core', 'debug')
0286   import_namespace_item('core', 'info')
0287   import_namespace_item('core', 'warning')
0288   import_namespace_item('core', 'error')
0289   import_namespace_item('core', 'fatal')
0290   import_namespace_item('core', 'exception')
0291 
0292   import_namespace_item('core', 'Detector')
0293   import_namespace_item('core', 'evaluator')
0294   import_namespace_item('core', 'g4Evaluator')
0295 
0296   import_namespace_item('core', 'VolumeManager')
0297   import_namespace_item('core', 'OverlayedField')
0298   import_namespace_item('core', 'Ref_t')
0299 
0300   # // Objects.h
0301   import_namespace_item('core', 'Author')
0302   import_namespace_item('core', 'Header')
0303   import_namespace_item('core', 'Constant')
0304   import_namespace_item('core', 'Atom')
0305   import_namespace_item('core', 'Material')
0306   import_namespace_item('core', 'VisAttr')
0307   import_namespace_item('core', 'Limit')
0308   import_namespace_item('core', 'LimitSet')
0309   import_namespace_item('core', 'LimitSetObject')
0310   import_namespace_item('core', 'Region')
0311   import_namespace_item('core', 'RegionObject')
0312   import_namespace_item('core', 'HitCollection')
0313   # // Typedefs from Objects.h
0314   import_namespace_item('core', 'Position')
0315   import_namespace_item('core', 'PositionRhoZPhi')
0316   import_namespace_item('core', 'PositionPolar')
0317   import_namespace_item('core', 'Direction')
0318   import_namespace_item('core', 'XYZAngles')
0319   import_namespace_item('core', 'RotationZYX')
0320   import_namespace_item('core', 'RotationX')
0321   import_namespace_item('core', 'RotationY')
0322   import_namespace_item('core', 'RotationZ')
0323   import_namespace_item('core', 'Rotation3D')
0324   import_namespace_item('core', 'EulerAngles')
0325   import_namespace_item('core', 'Transform3D')
0326   import_namespace_item('core', 'Translation3D')
0327 
0328   # // Readout.h
0329   import_namespace_item('core', 'Segmentation')
0330   import_namespace_item('core', 'SegmentationObject')
0331   import_namespace_item('core', 'Readout')
0332   import_namespace_item('core', 'ReadoutObject')
0333 
0334   # // Alignments.h
0335   import_namespace_item('core', 'Alignment')
0336   import_namespace_item('core', 'AlignmentCondition')
0337 
0338   # // Conditions.h
0339   import_namespace_item('core', 'Condition')
0340   import_namespace_item('core', 'ConditionKey')
0341 
0342   # // DetElement.h
0343   import_namespace_item('core', 'World')
0344   import_namespace_item('core', 'DetElement')
0345   import_namespace_item('core', 'SensitiveDetector')
0346 
0347   # // Volume.h
0348   import_namespace_item('core', 'Volume')
0349   import_namespace_item('core', 'PlacedVolume')
0350 
0351   # // Shapes.h
0352   import_namespace_item('core', 'Solid')
0353   import_namespace_item('core', 'Box')
0354   import_namespace_item('core', 'HalfSpace')
0355   import_namespace_item('core', 'Polycone')
0356   import_namespace_item('core', 'ConeSegment')
0357   import_namespace_item('core', 'Tube')
0358   import_namespace_item('core', 'CutTube')
0359   import_namespace_item('core', 'TruncatedTube')
0360   import_namespace_item('core', 'EllipticalTube')
0361   import_namespace_item('core', 'Cone')
0362   import_namespace_item('core', 'Trap')
0363   import_namespace_item('core', 'PseudoTrap')
0364   import_namespace_item('core', 'Trapezoid')
0365   import_namespace_item('core', 'Torus')
0366   import_namespace_item('core', 'Sphere')
0367   import_namespace_item('core', 'Paraboloid')
0368   import_namespace_item('core', 'Hyperboloid')
0369   import_namespace_item('core', 'PolyhedraRegular')
0370   import_namespace_item('core', 'Polyhedra')
0371   import_namespace_item('core', 'ExtrudedPolygon')
0372   import_namespace_item('core', 'EightPointSolid')
0373   import_namespace_item('core', 'BooleanSolid')
0374   import_namespace_item('core', 'SubtractionSolid')
0375   import_namespace_item('core', 'UnionSolid')
0376   import_namespace_item('core', 'IntersectionSolid')
0377 
0378 
0379 # ---------------------------------------------------------------------------
0380 def import_tgeo():
0381   import_root('TGeoManager')
0382   import_root('TGeoNode')
0383   import_root('TGeoNodeMatrix')
0384 
0385   import_root('TGeoVolume')
0386   import_root('TGeoVolumeMulti')
0387   import_root('TGeoVolumeAssembly')
0388 
0389   import_root('TGeoMaterial')
0390   import_root('TGeoMedium')
0391   import_root('TGeoIsotope')
0392   import_root('TGeoElement')
0393 
0394   import_root('TGeoMatrix')
0395   import_root('TGeoHMatrix')
0396   import_root('TGeoIdentity')
0397   import_root('TGeoTranslation')
0398   import_root('TGeoRotation')
0399   import_root('TGeoScale')
0400   import_root('TGeoCombiTrans')
0401 
0402   import_root('TGeoShape')
0403   import_root('TGeoBBox')
0404   import_root('TGeoArb8')
0405   import_root('TGeoTrap')
0406   import_root('TGeoGtra')
0407   import_root('TGeoCompositeShape')
0408   import_root('TGeoCone')
0409   import_root('TGeoConeSeg')
0410   import_root('TGeoTube')
0411   import_root('TGeoTubeSeg')
0412   import_root('TGeoCtub')
0413   import_root('TGeoEltu')
0414   import_root('TGeoHype')
0415   import_root('TGeoHalfSpace')
0416   import_root('TGeoPara')
0417   import_root('TGeoParaboloid')
0418   import_root('TGeoPcon')
0419   import_root('TGeoPgon')
0420   import_root('TGeoScaledShape')
0421   import_root('TGeoShapeAssembly')
0422   import_root('TGeoSphere')
0423   import_root('TGeoTorus')
0424   import_root('TGeoTrd1')
0425   import_root('TGeoTrd2')
0426   import_root('TGeoXtru')
0427 
0428 
0429 import_tgeo()
0430 import_geometry()
0431 import_detail()
0432 
0433 
0434 # ---------------------------------------------------------------------------
0435 class Logger:
0436   """
0437   Helper class to use the dd4hep printout functions from python
0438 
0439   \author  M.Frank
0440   \version 1.0
0441   """
0442 
0443   def __init__(self, name):
0444     "Logger constructor"
0445     self.name = name
0446 
0447   def setPrintLevel(self, level):
0448     "Adjust printout level of dd4hep"
0449     if isinstance(level, str):
0450       if level == 'VERBOSE':
0451         level = OutputLevel.VERBOSE
0452       elif level == 'DEBUG':
0453         level = OutputLevel.DEBUG
0454       elif level == 'INFO':
0455         level = OutputLevel.INFO
0456       elif level == 'WARNING':
0457         level = OutputLevel.WARNING
0458       elif level == 'ERROR':
0459         level = OutputLevel.ERROR
0460       elif level == 'FATAL':
0461         level = OutputLevel.FATAL
0462       else:
0463         level = int(level)
0464     dd4hep.setPrintLevel(level)
0465 
0466   def always(self, msg):
0467     "Call dd4hep printout function with level ALWAYS"
0468     dd4hep.always(self.name, msg)
0469 
0470   def verbose(self, msg):
0471     "Call dd4hep printout function with level VERBOSE"
0472     dd4hep.verbose(self.name, msg)
0473 
0474   def debug(self, msg):
0475     "Call dd4hep printout function with level DEBUG"
0476     dd4hep.debug(self.name, msg)
0477 
0478   def info(self, msg):
0479     "Call dd4hep printout function with level INFO"
0480     dd4hep.info(self.name, msg)
0481 
0482   def warning(self, msg):
0483     "Call dd4hep printout function with level WARNING"
0484     dd4hep.warning(self.name, msg)
0485 
0486   def error(self, msg):
0487     "Call dd4hep printout function with level ERROR"
0488     dd4hep.error(self.name, msg)
0489 
0490   def fatal(self, msg):
0491     "Call dd4hep printout function with level FATAL"
0492     dd4hep.fatal(self.name, msg)
0493 
0494   def exception(self, msg):
0495     "Call dd4hep exception function"
0496     dd4hep.exception(self.name, msg)
0497 
0498 
0499 dd4hep_logger = Logger
0500 
0501 
0502 # ---------------------------------------------------------------------------
0503 #
0504 # Helper: Command line interpreter
0505 #
0506 # ---------------------------------------------------------------------------
0507 class CommandLine:
0508   """
0509   Helper to ease parsing the command line.
0510   Any argument given in the command line is accessible
0511   from the object. If no value is supplied, the returned
0512   value is True. If the argument is not present None is returned.
0513 
0514   \author  M.Frank
0515   \version 1.0
0516   """
0517   def __init__(self, help=None):  # noqa: A002
0518     import sys
0519     self.data = {}
0520     help_call = help
0521     have_help = False
0522     for i in range(len(sys.argv)):
0523       if sys.argv[i][0] == '-':
0524         key = sys.argv[i][1:]
0525         val = True
0526         if i + 1 < len(sys.argv):
0527           v = sys.argv[i + 1]
0528           if v[0] != '-':
0529             val = v
0530         self.data[key] = val
0531         if key.upper() == 'HELP' or key.upper() == '?':
0532          have_help = True
0533     if have_help and help_call:
0534       help_call()
0535     if self.data.get('print_level'):
0536       log = Logger('CommandLine')
0537       log.setPrintLevel(self.data.get('print_level'))
0538 
0539   def __getattr__(self, attr):
0540     if self.data.get(attr):
0541       return self.data.get(attr)
0542     return None
0543 
0544 
0545 # ---------------------------------------------------------------------------
0546 #
0547 #  Import units from TGeo.
0548 #  Calling import_units makes all the units local to the dd4hep module.
0549 #
0550 try:
0551   import_namespace_item('core', 'dd4hep_units')
0552 
0553   def import_units(ns=None):
0554     if ns is None:
0555       ns = name_space
0556 
0557     logger.debug('Importing units into namespace ' + str(ns.__name__))
0558     count = 0
0559     for nam in dir(dd4hep.dd4hep_units):
0560       if nam[0] != '_':
0561         count = count + 1
0562         setattr(ns, nam, getattr(core.dd4hep_units, nam))
0563         # setattr(ns, nam, getattr(core, nam))
0564     return count
0565 
0566 except Exception as e:
0567   logger.warning('No units can be imported. ' + str(e))
0568 
0569   def import_units(ns=None):
0570     return 0
0571 
0572 import_units(ns=units)