import os import sys import math from pathlib import Path from typing import Optional import acts import acts.examples import acts.tgeo from acts import root import warnings def getOpenDataDetectorDirectory(): odd_dir = os.environ.get("ODD_PATH") if odd_dir is None: raise RuntimeError("ODD_PATH environment variable not set") odd_dir = Path(odd_dir) return odd_dir def getOpenDataDetector( materialDecorator=None, misaligned=False, odd_dir: Optional[Path] = None, logLevel=acts.logging.INFO, gen3=False, constructionMethod=None, ): """This function sets up the open data detector. Requires DD4hep. Parameters ---------- materialDecorator: Material Decorator, take RootMaterialDecorator if non is given odd_dir: if not given, try to get via ODD_PATH environment variable logLevel: logging level constructionMethod: Gen3 conversion method enum value of OpenDataDetector.Config.ConstructionMethod use `ConstructionMethod.TGeo` for the TGeo-backed Gen3 path """ import acts.examples.dd4hep customLogLevel = acts.examples.defaultLogging(logLevel=logLevel) if odd_dir is None: odd_dir = getOpenDataDetectorDirectory() if not odd_dir.exists(): raise RuntimeError(f"OpenDataDetector not found at {odd_dir}") odd_xml = odd_dir / "xml" / "OpenDataDetector.xml" if not odd_xml.exists(): raise RuntimeError(f"OpenDataDetector.xml not found at {odd_xml}") env_vars = [] map_name = "libOpenDataDetector.components" lib_name = None if sys.platform == "linux": env_vars = ["LD_LIBRARY_PATH"] lib_name = "libOpenDataDetector.so" elif sys.platform == "darwin": env_vars = ["DYLD_LIBRARY_PATH", "DD4HEP_LIBRARY_PATH"] lib_name = "libOpenDataDetector.dylib" if lib_name is not None and len(env_vars) > 0: found = False for env_var in env_vars: for lib_dir in os.environ.get(env_var, "").split(":"): lib_dir = Path(lib_dir) if (lib_dir / map_name).exists() and (lib_dir / lib_name).exists(): found = True break if not found: msg = ( "Unable to find OpenDataDetector factory library. " f"You might need to point {'/'.join(env_vars)} to the ODD install location." f"It might be at {odd_dir / 'factory'}" ) raise RuntimeError(msg) if materialDecorator is None: materialDecorator = acts.root.RootMaterialDecorator( fileName=str(odd_dir / "data/odd-material-maps.root"), level=customLogLevel(minLevel=acts.logging.WARNING), ) if gen3: if misaligned: raise InvalidArgumentError( "Gen3 ODD currently does not support misalignment" ) oddConfig = acts.examples.dd4hep.OpenDataDetector.Config( xmlFileNames=[str(odd_xml)], name="OpenDataDetector", logLevel=customLogLevel(), dd4hepLogLevel=customLogLevel(minLevel=acts.logging.WARNING), ) if constructionMethod is not None: oddConfig.constructionMethod = constructionMethod # Use default constructed geometry context. This will have to change if DD4hep gains alignment awareness. gctx = acts.GeometryContext.dangerouslyDefaultConstruct() with warnings.catch_warnings(): warnings.simplefilter("ignore") detector = acts.examples.dd4hep.OpenDataDetector( config=oddConfig, gctx=gctx ) return detector else: volumeRadiusCutsMap = { 28: [850.0], # LStrip negative z 30: [850.0], # LStrip positive z 23: [400.0, 550.0], # SStrip negative z 25: [400.0, 550.0], # SStrip positive z 16: [100.0], # Pixels negative z 18: [100.0], # Pixels positive z } def geoid_hook(geoid, surface): gctx = acts.GeometryContext.dangerouslyDefaultConstruct() if geoid.volume in volumeRadiusCutsMap: r = math.sqrt( surface.center(gctx)[0] ** 2 + surface.center(gctx)[1] ** 2 ) geoid.extra = 1 for cut in volumeRadiusCutsMap[geoid.volume]: if r > cut: geoid.extra += 1 return geoid dd4hepConfig = acts.examples.dd4hep.DD4hepDetector.Config( xmlFileNames=[str(odd_xml)], name="OpenDataDetector", logLevel=customLogLevel(), dd4hepLogLevel=customLogLevel(minLevel=acts.logging.WARNING), geometryIdentifierHook=acts.GeometryIdentifierHook(geoid_hook), materialDecorator=materialDecorator, ) if misaligned: dd4hepConfig.detectorElementFactory = ( acts.examples.dd4hep.alignedDD4hepDetectorElementFactory ) with warnings.catch_warnings(): warnings.simplefilter("ignore") detector = acts.examples.dd4hep.DD4hepDetector(dd4hepConfig) return detector