From ab6eaf38670b30b26254439659fa0377b44d0620 Mon Sep 17 00:00:00 2001 From: John William Spencer <john.william.spencer@cern.ch> Date: Tue, 9 Feb 2021 00:13:25 +0000 Subject: [PATCH] implement materialmapping in calypso --- .../G4FaserAlg/python/G4FaserAlgConfigNew.py | 106 ++ .../G4FaserAlg/test/runGeantinoScan.py | 139 +++ .../python/G4FaserUserActionConfigNew.py | 36 +- .../python/G4UserActionsConfigNew.py | 7 + .../Acts/FaserActsGeometry/CMakeLists.txt | 19 +- .../FaserActsJsonGeometryConverter.h | 261 ++++ .../FaserActsMaterialJsonWriterTool.h | 60 + .../FaserActsMaterialMapping.h | 74 ++ .../FaserActsSurfaceMappingTool.h | 65 + .../FaserActsVolumeMappingTool.h | 66 + .../python/ActsGeometryConfig.py | 166 +++ .../FaserActsMaterialMapping_jobOptions.py | 109 ++ .../src/FaserActsJsonGeometryConverter.cxx | 1069 +++++++++++++++++ .../src/FaserActsMaterialJsonWriterTool.cxx | 62 + .../src/FaserActsMaterialMapping.cxx | 135 +++ .../src/FaserActsSurfaceMappingTool.cxx | 67 ++ .../src/FaserActsVolumeMappingTool.cxx | 69 ++ .../components/FaserActsGeometry_entries.cxx | 9 +- .../CMakeLists.txt | 4 +- .../IFaserActsMaterialJsonWriterTool.h | 36 + .../IFaserActsSurfaceMappingTool.h | 37 + .../IFaserActsTrackingGeometryTool.h | 4 +- .../IFaserActsVolumeMappingTool.h | 37 + 23 files changed, 2628 insertions(+), 9 deletions(-) create mode 100644 Simulation/G4Faser/G4FaserAlg/test/runGeantinoScan.py create mode 100644 Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsJsonGeometryConverter.h create mode 100644 Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsMaterialJsonWriterTool.h create mode 100644 Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsMaterialMapping.h create mode 100644 Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsSurfaceMappingTool.h create mode 100644 Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsVolumeMappingTool.h create mode 100644 Tracking/Acts/FaserActsGeometry/python/ActsGeometryConfig.py create mode 100644 Tracking/Acts/FaserActsGeometry/python/FaserActsMaterialMapping_jobOptions.py create mode 100644 Tracking/Acts/FaserActsGeometry/src/FaserActsJsonGeometryConverter.cxx create mode 100644 Tracking/Acts/FaserActsGeometry/src/FaserActsMaterialJsonWriterTool.cxx create mode 100644 Tracking/Acts/FaserActsGeometry/src/FaserActsMaterialMapping.cxx create mode 100644 Tracking/Acts/FaserActsGeometry/src/FaserActsSurfaceMappingTool.cxx create mode 100644 Tracking/Acts/FaserActsGeometry/src/FaserActsVolumeMappingTool.cxx create mode 100644 Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsMaterialJsonWriterTool.h create mode 100644 Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsSurfaceMappingTool.h create mode 100644 Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsVolumeMappingTool.h diff --git a/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py b/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py index 292682b4..7e24163a 100644 --- a/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py +++ b/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py @@ -8,6 +8,7 @@ from AthenaConfiguration.ComponentFactory import CompFactory from G4FaserServices.G4FaserServicesConfigNew import DetectorGeometrySvcCfg, PhysicsListSvcCfg from G4FaserTools.G4FaserToolsConfigNew import SensitiveDetectorMasterToolCfg from G4FaserServices.G4FaserUserActionConfigNew import UserActionSvcCfg +from G4FaserServices.G4FaserUserActionConfigNew import UserActionMaterialStepRecorderSvcCfg # from G4AtlasApps.G4Atlas_MetadataNew import writeSimulationParametersMetadata # # Framework utilities @@ -122,3 +123,108 @@ def G4FaserAlgCfg(ConfigFlags, name='G4FaserAlg', **kwargs): result.addEventAlgo(G4FaserAlg(name, **kwargs)) return result +def G4FaserMaterialStepRecorderAlgCfg(ConfigFlags, name='G4FaserAlg', **kwargs): + # + # add Services to G4AtlasAlg + # + result = DetectorGeometrySvcCfg(ConfigFlags) + kwargs.setdefault('DetGeoSvc', result.getService("DetectorGeometrySvc")) + # + # MC particle container names + # + kwargs.setdefault("InputTruthCollection", "GEN_EVENT") + kwargs.setdefault("OutputTruthCollection", "TruthEvent") + # + # Option to free memory by dropping GeoModel after construction + # + # if ConfigFlags.Sim.ReleaseGeoModel: + kwargs.setdefault('ReleaseGeoModel', ConfigFlags.Sim.ReleaseGeoModel) + # + # Record the particle flux during the simulation + # + #if ConfigFlags.Sim.RecordFlux: + kwargs.setdefault('RecordFlux' , ConfigFlags.Sim.RecordFlux) + # + # Treatment of bad events + # + # if ConfigFlags.Sim.FlagAbortedEvents: + ## default false + kwargs.setdefault('FlagAbortedEvents' ,ConfigFlags.Sim.FlagAbortedEvents) + if ConfigFlags.Sim.FlagAbortedEvents and ConfigFlags.Sim.KillAbortedEvents: + print('WARNING When G4AtlasAlg.FlagAbortedEvents is True G4AtlasAlg.KillAbortedEvents should be False!!! Setting G4AtlasAlg.KillAbortedEvents = False now!') + kwargs.setdefault('KillAbortedEvents' ,False) + # if ConfigFlags.Sim.KillAbortedEvents: + ## default true + kwargs.setdefault('KillAbortedEvents' ,ConfigFlags.Sim.KillAbortedEvents) + # + # Random numbers + # + from RngComps.RandomServices import AthEngines, RNG + if ConfigFlags.Random.Engine in AthEngines.keys(): + result.merge(RNG(ConfigFlags.Random.Engine, name="AthRNGSvc")) + kwargs.setdefault("AtRndmGenSvc",result.getService("AthRNGSvc")) + + kwargs.setdefault("RandomGenerator", "athena") + # + # Multi-threading settings + # + is_hive = ConfigFlags.Concurrency.NumThreads > 1 + kwargs.setdefault('MultiThreading', is_hive) + # + # What truth information to save? + # + accMCTruth = FaserTruthServiceCfg(ConfigFlags) + result.merge(accMCTruth) + kwargs.setdefault('TruthRecordService', result.getService("FaserISF_TruthService")) + #kwargs.setdefault('TruthRecordService', ConfigFlags.Sim.TruthStrategy) # TODO need to have manual override (simFlags.TruthStrategy.TruthServiceName()) + # + # Locates detector region for space points (no longer used by G4FaserAlg) + # + accGeoID = FaserGeoIDSvcCfg(ConfigFlags) + result.merge(accGeoID) + #kwargs.setdefault('GeoIDSvc', result.getService('ISF_FaserGeoIDSvc')) + # + # Converts generator particles to a proprietary type managed by ISF + # + accInputConverter = FaserInputConverterCfg(ConfigFlags) + result.merge(accInputConverter) + kwargs.setdefault('InputConverter', result.getService("ISF_FaserInputConverter")) + # + # Sensitive detector master tool + # + accSensitiveDetector = SensitiveDetectorMasterToolCfg(ConfigFlags) + result.merge(accSensitiveDetector) + kwargs.setdefault('SenDetMasterTool', result.getPublicTool("SensitiveDetectorMasterTool")) #NOTE - is still a public tool + # + #Write MetaData container + # + #result.merge(writeSimulationParametersMetadata(ConfigFlags)) + # + #User action services (Slow...) + # + result.merge(UserActionMaterialStepRecorderSvcCfg(ConfigFlags) ) + kwargs.setdefault('UserActionSvc', result.getService( "G4UA::UserActionSvc") ) + + #PhysicsListSvc + result.merge( PhysicsListSvcCfg(ConfigFlags) ) + kwargs.setdefault('PhysicsListSvc', result.getService( "PhysicsListSvc") ) + + # + # Output level + # + ## G4AtlasAlg verbosities (available domains = Navigator, Propagator, Tracking, Stepping, Stacking, Event) + ## Set stepper verbose = 1 if the Athena logging level is <= DEBUG + # TODO: Why does it complain that G4AtlasAlgConf.G4AtlasAlg has no "Verbosities" object? Fix. + verbosities=dict(Placeholder = '0') + if "OutputLevel" in kwargs and kwargs["OutputLevel"] <= 2 : + verbosities["Tracking"]='1' + print (verbosities) + kwargs.setdefault('Verbosities', verbosities) + # + # Set commands for the G4FaserAlg + # + kwargs.setdefault("G4Commands", ConfigFlags.Sim.G4Commands) + + result.addEventAlgo(G4FaserAlg(name, **kwargs)) + return result + diff --git a/Simulation/G4Faser/G4FaserAlg/test/runGeantinoScan.py b/Simulation/G4Faser/G4FaserAlg/test/runGeantinoScan.py new file mode 100644 index 00000000..5a35c670 --- /dev/null +++ b/Simulation/G4Faser/G4FaserAlg/test/runGeantinoScan.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python +if __name__ == "__main__": + import os + import sys + import GaudiPython + import ParticleGun as PG + from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator + from AthenaConfiguration.ComponentFactory import CompFactory + from AthenaCommon.AppMgr import * + from AthenaCommon.Logging import log, logging + from AthenaCommon.SystemOfUnits import TeV + from AthenaCommon.PhysicalConstants import pi + from AthenaCommon.Constants import VERBOSE, INFO + from AthenaCommon.Configurable import Configurable + from CalypsoConfiguration.AllConfigFlags import ConfigFlags + from CalypsoConfiguration.MainServicesConfig import MainServicesCfg + from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg + from McEventSelector.McEventSelectorConfig import McEventSelectorCfg + from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg + from FaserGeoModel.FaserGeoModelConfig import FaserGeometryCfg + from G4FaserAlg.G4FaserAlgConfigNew import G4FaserAlgCfg + from G4FaserAlg.G4FaserAlgConfigNew import G4FaserMaterialStepRecorderAlgCfg + from G4FaserServices.G4FaserServicesConfigNew import G4GeometryNotifierSvcCfg +# +# Set up logging and new style config +# + log.setLevel(VERBOSE) + Configurable.configurableRun3Behavior = True +# +# Input settings (Generator file) +# +# from AthenaConfiguration.TestDefaults import defaultTestFiles +# ConfigFlags.Input.Files = defaultTestFiles.EVNT +# +# Alternatively, these must ALL be explicitly set to run without an input file +# (if missing, it will try to read metadata from a non-existent file and crash) +# + ConfigFlags.Input.Files = [""] + ConfigFlags.Input.isMC = True + ConfigFlags.Input.RunNumber = 12345 + ConfigFlags.Input.Collections = [""] + ConfigFlags.Input.ProjectName = "mc19" + ConfigFlags.Common.isOnline = False + ConfigFlags.Beam.Type = "collisions" + ConfigFlags.Beam.Energy = 7*TeV # Informational, does not affect simulation + ConfigFlags.GeoModel.FaserVersion = "FASER-01" # Always needed + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-XXXX-XXX-XX" # Always needed; only the OFLCOND part matters +# Workaround for bug/missing flag; unimportant otherwise + ConfigFlags.addFlag("Input.InitialTimeStamp", 0) +# Workaround to avoid problematic ISF code + ConfigFlags.GeoModel.Layout = "Development" +# +# Output settings +# + ConfigFlags.Output.HITSFileName = "MaterialStepCollection.root" + ConfigFlags.GeoModel.GeoExportFile = "faserGeo.db" # Optional dump of geometry for browsing in vp1light +# +# Geometry-related settings +# Do not change! +# + ConfigFlags.Detector.SimulateVeto = True + ConfigFlags.Detector.GeometryVeto = True + ConfigFlags.Detector.SimulateTrigger= True + ConfigFlags.Detector.GeometryTrigger= True + ConfigFlags.Detector.SimulatePreshower = True + ConfigFlags.Detector.GeometryPreshower = True + ConfigFlags.Detector.SimulateFaserSCT = True + ConfigFlags.Detector.GeometryFaserSCT = True + ConfigFlags.Detector.SimulateUpstreamDipole = True + ConfigFlags.Detector.SimulateCentralDipole = True + ConfigFlags.Detector.SimulateDownstreamDipole = True + ConfigFlags.Detector.GeometryUpstreamDipole = True + ConfigFlags.Detector.GeometryCentralDipole = True + ConfigFlags.Detector.GeometryDownstreamDipole = True + ConfigFlags.GeoModel.Align.Dynamic = False + ConfigFlags.Sim.ReleaseGeoModel = False +# +# All flags should be set before calling lock +# + ConfigFlags.lock() +# +# Construct ComponentAccumulator +# + acc = MainServicesCfg(ConfigFlags) +# +# Particle Gun generator (comment out to read generator file) +# Raw energies (without units given) are interpreted as MeV +# + pg = PG.ParticleGun() + pg.McEventKey = "GEN_EVENT" + pg.randomSeed = 123456 + pg.sampler.pid = 999 + pg.sampler.mom = PG.EThetaMPhiSampler(energy=1*TeV, theta=[0, pi/20], phi=[0, 2*pi]) + pg.sampler.pos = PG.PosSampler(x=[-5, 5], y=[-5, 5], z=-2100.0, t=0.0) + acc.addEventAlgo(pg, "AthBeginSeq") # to run *before* G4 +# +# Only one of these two should be used in a given job +# (MCEventSelectorCfg for generating events with no input file, +# PoolReadCfg when reading generator data from an input file) +# + acc.merge(McEventSelectorCfg(ConfigFlags)) + # acc.merge(PoolReadCfg(ConfigFlags)) +# +# Output stream configuration +# + acc.merge(OutputStreamCfg(ConfigFlags, + "HITS", + ["EventInfo#*", + "McEventCollection#TruthEvent", + "McEventCollection#GEN_EVENT", + "Trk::MaterialStepCollection#*", + "ScintHitCollection#*", + "FaserSiHitCollection#*" + ], disableEventTag=True)) + acc.getEventAlgo("OutputStreamHITS").AcceptAlgs = ["G4FaserAlg"] # optional + acc.getEventAlgo("OutputStreamHITS").WritingTool.ProcessingTag = "StreamHITS" # required +# +# Here is the configuration of the Geant4 pieces +# + acc.merge(FaserGeometryCfg(ConfigFlags)) + acc.merge(G4FaserMaterialStepRecorderAlgCfg(ConfigFlags)) + acc.addService(G4GeometryNotifierSvcCfg(ConfigFlags, ActivateLVNotifier=True)) +# +# Verbosity +# +# ConfigFlags.dump() +# logging.getLogger('forcomps').setLevel(VERBOSE) +# acc.foreach_component("*").OutputLevel = VERBOSE +# acc.foreach_component("*ClassID*").OutputLevel = INFO +# acc.getService("StoreGateSvc").Dump=True +# acc.getService("ConditionStore").Dump=True +# acc.printConfig() + f=open('FaserG4AppCfg_EVNT.pkl','wb') + acc.store(f) + f.close() +# +# Execute and finish +# + sys.exit(int(acc.run(maxEvents=20000).isFailure())) diff --git a/Simulation/G4Faser/G4FaserServices/python/G4FaserUserActionConfigNew.py b/Simulation/G4Faser/G4FaserServices/python/G4FaserUserActionConfigNew.py index 3c54dd5d..588c6f6d 100644 --- a/Simulation/G4Faser/G4FaserServices/python/G4FaserUserActionConfigNew.py +++ b/Simulation/G4Faser/G4FaserServices/python/G4FaserUserActionConfigNew.py @@ -6,7 +6,7 @@ from AthenaConfiguration.ComponentFactory import CompFactory G4UA__UserActionSvc=CompFactory.G4UA.UserActionSvc -from G4UserActions.G4UserActionsConfigNew import AthenaStackingActionToolCfg, AthenaTrackingActionToolCfg +from G4UserActions.G4UserActionsConfigNew import AthenaStackingActionToolCfg, AthenaTrackingActionToolCfg, AthenaMaterialStepRecorderToolCfg # New function for all user action types @@ -60,6 +60,40 @@ def getDefaultActions(ConfigFlags): return actions +# add MaterialStepRecorderTool for Geantino scan and MaterialMapping +def getMaterialStepRecorderActions(ConfigFlags): + result = ComponentAccumulator() + + actions = [] + + actions += [result.popToolsAndMerge( AthenaStackingActionToolCfg(ConfigFlags) )] + + actions += [result.popToolsAndMerge( AthenaMaterialStepRecorderToolCfg(ConfigFlags) )] + + actions += [result.popToolsAndMerge( AthenaTrackingActionToolCfg(ConfigFlags) )] + + return actions + +def UserActionMaterialStepRecorderSvcCfg(ConfigFlags, name="G4UA::UserActionSvc", **kwargs): + """ + Get the standard UA svc configurable with all default actions added. + This function is normally called by the configured factory, not users. + """ + result = ComponentAccumulator() + + #how to convert this flag? + # from G4AtlasApps.SimFlags import simFlags + # optActions = simFlags.OptionalUserActionList.get_Value() + # new user action tools + kwargs.setdefault('UserActionTools', + getMaterialStepRecorderActions(ConfigFlags)) + + # placeholder for more advanced config, if needed + result.addService ( G4UA__UserActionSvc(name, **kwargs) ) + + return result + + def UserActionSvcCfg(ConfigFlags, name="G4UA::UserActionSvc", **kwargs): """ Get the standard UA svc configurable with all default actions added. diff --git a/Simulation/G4Utilities/G4UserActions/python/G4UserActionsConfigNew.py b/Simulation/G4Utilities/G4UserActions/python/G4UserActionsConfigNew.py index 4f37ffb4..ecac4c26 100644 --- a/Simulation/G4Utilities/G4UserActions/python/G4UserActionsConfigNew.py +++ b/Simulation/G4Utilities/G4UserActions/python/G4UserActionsConfigNew.py @@ -4,6 +4,7 @@ from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory G4UA__AthenaStackingActionTool=CompFactory.G4UA.AthenaStackingActionTool G4UA__AthenaTrackingActionTool=CompFactory.G4UA.AthenaTrackingActionTool +G4UA__AthenaMaterialStepRecorderTool=CompFactory.G4UA.MaterialStepRecorderTool # this is a bit cumbersome, but it seems ike it is a lot easier to separate # the getter functionality from all the rest (i.e. adding the action). @@ -53,3 +54,9 @@ def AthenaTrackingActionToolCfg(ConfigFlags, name='G4UA::AthenaTrackingActionToo kwargs.setdefault('SubDetVolumeLevel', subDetLevel) result.setPrivateTools( G4UA__AthenaTrackingActionTool(name,**kwargs) ) return result + +def AthenaMaterialStepRecorderToolCfg(ConfigFlags, name='G4UA::MaterialStepRecorderTool', **kwargs): + result = ComponentAccumulator() + + result.setPrivateTools( G4UA__AthenaMaterialStepRecorderTool(name,**kwargs) ) + return result diff --git a/Tracking/Acts/FaserActsGeometry/CMakeLists.txt b/Tracking/Acts/FaserActsGeometry/CMakeLists.txt index 260732e2..28b8c22e 100755 --- a/Tracking/Acts/FaserActsGeometry/CMakeLists.txt +++ b/Tracking/Acts/FaserActsGeometry/CMakeLists.txt @@ -6,26 +6,30 @@ atlas_subdir( FaserActsGeometry ) find_package( CLHEP ) find_package( Eigen ) find_package( Boost ) +find_package( nlohmann_json ) find_package( Acts COMPONENTS Core ) atlas_add_library( FaserActsGeometryLib - FaserActsGeometry/FaserActsGeometryContext.h - FaserActsGeometry/FaserActsDetectorElement.h + src/FaserActsSurfaceMappingTool.cxx + src/FaserActsMaterialMapping.cxx src/FaserActsAlignmentStore.cxx src/FaserActsDetectorElement.cxx src/FaserActsLayerBuilder.cxx src/CuboidVolumeBuilder.cxx + src/FaserActsJsonGeometryConverter.cxx src/util/*.cxx PUBLIC_HEADERS FaserActsGeometry INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${BOOST_INCLUDE_DIRS} - LINK_LIBRARIES ${CLHEP_LIBRARIES} ${EIGEN_LIBRARIES} ${BOOST_LIBRARIES} + LINK_LIBRARIES ${CLHEP_LIBRARIES} ${EIGEN_LIBRARIES} ${BOOST_LIBRARIES} nlohmann_json::nlohmann_json TrackerIdentifier TrackerReadoutGeometry ActsInteropLib FaserActsGeometryInterfacesLib AthenaKernel ActsCore + ActsGeometryLib + ActsGeometryInterfacesLib MagFieldInterfaces MagFieldElements MagFieldConditions @@ -37,12 +41,17 @@ atlas_add_library( FaserActsGeometryLib TrackerIdentifier TrackerPrepRawData TrkSpacePoint + TrkGeometry ) # Component(s) in the package: atlas_add_component( FaserActsGeometry ##src/*.cxx + src/FaserActsSurfaceMappingTool.cxx + src/FaserActsMaterialMapping.cxx + src/FaserActsMaterialJsonWriterTool.cxx + src/FaserActsJsonGeometryConverter.cxx src/FaserActsTrackingGeometrySvc.cxx src/FaserActsTrackingGeometryTool.cxx src/FaserActsWriteTrackingGeometry.cxx @@ -53,6 +62,7 @@ atlas_add_component( FaserActsGeometry src/FaserActsAlignmentCondAlg.cxx src/NominalAlignmentCondAlg.cxx #src/FaserActsKalmanFilterAlg.cxx + src/FaserActsVolumeMappingTool.cxx src/components/*.cxx PUBLIC_HEADERS FaserActsGeometry INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${BOOST_INCLUDE_DIRS} @@ -64,6 +74,8 @@ atlas_add_component( FaserActsGeometry ActsInteropLib FaserActsGeometryInterfacesLib ActsCore + ActsGeometryLib + ActsGeometryInterfacesLib MagFieldInterfaces MagFieldElements MagFieldConditions @@ -75,6 +87,7 @@ atlas_add_component( FaserActsGeometry TrackerIdentifier TrackerPrepRawData TrkSpacePoint + TrkGeometry ) diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsJsonGeometryConverter.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsJsonGeometryConverter.h new file mode 100644 index 00000000..2936c9d3 --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsJsonGeometryConverter.h @@ -0,0 +1,261 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2017-2019 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Material/ISurfaceMaterial.hpp" +#include "Acts/Material/IVolumeMaterial.hpp" +#include "Acts/Material/MaterialSlab.hpp" +#include "Acts/Utilities/BinUtility.hpp" +#include "Acts/Utilities/Definitions.hpp" +#include "Acts/Utilities/Logger.hpp" +#include <Acts/Geometry/TrackingVolume.hpp> +#include <Acts/Surfaces/Surface.hpp> + +#include <map> + +#include <nlohmann/json.hpp> + +namespace Acts { + +/// @class FaserActsJsonGeometryConverter +/// +/// @brief read the material from Json +class FaserActsJsonGeometryConverter { + public: + using SurfaceMaterialMap = + std::map<GeometryIdentifier, std::shared_ptr<const ISurfaceMaterial>>; + + using VolumeMaterialMap = + std::map<GeometryIdentifier, std::shared_ptr<const IVolumeMaterial>>; + + using DetectorMaterialMaps = std::pair<SurfaceMaterialMap, VolumeMaterialMap>; + + using geo_id_value = uint64_t; + + using SurfaceMaterialRep = std::map<geo_id_value, const ISurfaceMaterial*>; + using SurfaceRep = std::map<geo_id_value, const Surface*>; + using VolumeMaterialRep = std::map<geo_id_value, const IVolumeMaterial*>; + + /// @brief Layer representation for Json writing + struct LayerRep { + // the layer id + GeometryIdentifier layerID; + + SurfaceMaterialRep sensitives; + SurfaceRep sensitiveSurfaces; + SurfaceMaterialRep approaches; + SurfaceRep approacheSurfaces; + const ISurfaceMaterial* representing = nullptr; + const Surface* representingSurface = nullptr; + + /// The LayerRep is actually worth it to write out + operator bool() const { + return (!sensitives.empty() or !approaches.empty() or + representing != nullptr); + } + }; + + /// @brief Volume representation for Json writing + struct VolumeRep { + // The geometry id + GeometryIdentifier volumeID; + + /// The namne + std::string volumeName; + + std::map<geo_id_value, LayerRep> layers; + SurfaceMaterialRep boundaries; + SurfaceRep boundarySurfaces; + const IVolumeMaterial* material = nullptr; + + /// The VolumeRep is actually worth it to write out + operator bool() const { + return (!layers.empty() or !boundaries.empty() or material != nullptr); + } + }; + + /// @brief Detector representation for Json writing + struct DetectorRep { + std::map<geo_id_value, VolumeRep> volumes; + }; + + /// @class Config + /// Configuration of the Reader + class Config { + public: + /// The geometry version + std::string geoversion = "undefined"; + /// The detector tag + std::string detkey = "detector"; + /// The volume identification string + std::string volkey = "volumes"; + /// The name identification + std::string namekey = "Name"; + /// The boundary surface string + std::string boukey = "boundaries"; + /// The layer identification string + std::string laykey = "layers"; + /// The volume material string + std::string matkey = "material"; + /// The approach identification string + std::string appkey = "approach"; + /// The sensitive identification string + std::string senkey = "sensitive"; + /// The representing idntification string + std::string repkey = "representing"; + /// The bin keys + std::string bin0key = "bin0"; + /// The bin1 key + std::string bin1key = "bin1"; + /// The bin2 key + std::string bin2key = "bin2"; + /// The local to global tranfo key + std::string transfokeys = "tranformation"; + /// The type key -> proto, else + std::string typekey = "type"; + /// The data key + std::string datakey = "data"; + /// The geoid key + std::string geometryidkey = "Geoid"; + /// The surface geoid key + std::string surfacegeometryidkey = "SGeoid"; + /// The mapping key, add surface to map if true + std::string mapkey = "mapMaterial"; + /// The surface type key + std::string surfacetypekey = "stype"; + /// The surface position key + std::string surfacepositionkey = "sposition"; + /// The surface range key + std::string surfacerangekey = "srange"; + /// The default logger + std::shared_ptr<const Logger> logger; + /// The name of the writer + std::string name = ""; + + /// Steering to handle sensitive data + bool processSensitives = true; + /// Steering to handle approach data + bool processApproaches = true; + /// Steering to handle representing data + bool processRepresenting = true; + /// Steering to handle boundary data + bool processBoundaries = true; + /// Steering to handle volume data + bool processVolumes = true; + /// Steering to handle volume data + bool processDenseVolumes = false; + /// Add proto material to all surfaces + bool processnonmaterial = false; + /// Write out data + bool writeData = true; + + /// Constructor + /// + /// @param lname Name of the writer tool + /// @param lvl The output logging level + Config(const std::string& lname = "FaserActsJsonGeometryConverter", + Logging::Level lvl = Logging::INFO) + : logger(getDefaultLogger(lname, lvl)), name(lname) {} + }; + + /// Constructor + /// + /// @param cfg configuration struct for the reader + FaserActsJsonGeometryConverter(const Config& cfg); + + /// Destructor + ~FaserActsJsonGeometryConverter() = default; + + /// Convert method + /// + /// @param surfaceMaterialMap The indexed material map collection + std::pair< + std::map<GeometryIdentifier, std::shared_ptr<const ISurfaceMaterial>>, + std::map<GeometryIdentifier, std::shared_ptr<const IVolumeMaterial>>> + jsonToMaterialMaps(const nlohmann::json& materialmaps); + + /// Convert method + /// + /// @param surfaceMaterialMap The indexed material map collection + nlohmann::json materialMapsToJson(const DetectorMaterialMaps& maps); + + /// Write method + /// + /// @param tGeometry is the tracking geometry which contains the material + nlohmann::json trackingGeometryToJson(const TrackingGeometry& tGeometry); + + private: + /// Convert to internal representation method, recursive call + /// + /// @param tGeometry is the tracking geometry which contains the material + void convertToRep(DetectorRep& detRep, const TrackingVolume& tVolume); + + /// Convert to internal representation method + /// + /// @param tGeometry is the tracking geometry which contains the material + LayerRep convertToRep(const Layer& tLayer); + + /// Create the Surface Material from Json + /// - factory method, ownership given + /// @param material is the json part representing a material object + const ISurfaceMaterial* jsonToSurfaceMaterial(const nlohmann::json& material); + + /// Create the Volume Material from Json + /// - factory method, ownership given + /// @param material is the json part representing a material object + const IVolumeMaterial* jsonToVolumeMaterial(const nlohmann::json& material); + + /// Create the Material Matrix from Json + /// + /// @param data is the json part representing a material data array + MaterialSlabMatrix jsonToMaterialMatrix(const nlohmann::json& data); + + /// Create the BinUtility for from Json + BinUtility jsonToBinUtility(const nlohmann::json& bin); + + /// Create the local to global transform for from Json + Transform3D jsonToTransform(const nlohmann::json& transfo); + + /// Create Json from a detector represenation + nlohmann::json detectorRepToJson(const DetectorRep& detRep); + + /// SurfaceMaterial to Json + /// + /// @param the SurfaceMaterial + nlohmann::json surfaceMaterialToJson(const ISurfaceMaterial& sMaterial); + + /// VolumeMaterial to Json + /// + /// @param the VolumeMaterial + nlohmann::json volumeMaterialToJson(const IVolumeMaterial& vMaterial); + + /// Add surface information to json surface + /// + /// @param The json surface The surface + void addSurfaceToJson(nlohmann::json& sjson, const Surface* surface); + + /// Default BinUtility to create proto material + /// + /// @param the Surface + Acts::BinUtility DefaultBin(const Acts::Surface& surface); + + /// Default BinUtility to create proto material + /// + /// @param the Volume + Acts::BinUtility DefaultBin(const Acts::TrackingVolume& volume); + + /// The config class + Config m_cfg; + + /// Private access to the logging instance + const Logger& logger() const { return *m_cfg.logger; } +}; + +} // namespace Acts diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsMaterialJsonWriterTool.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsMaterialJsonWriterTool.h new file mode 100644 index 00000000..e3959e30 --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsMaterialJsonWriterTool.h @@ -0,0 +1,60 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ACTSGEOMETRY_FASERACTSMATERIALJSONWRITERTOOL_H +#define ACTSGEOMETRY_FASERACTSMATERIALJSONWRITERTOOL_H + +// ATHENA +#include "AthenaBaseComps/AthAlgTool.h" +#include "AthenaBaseComps/AthService.h" +#include "GaudiKernel/IInterface.h" +#include "Gaudi/Property.h" /*no forward decl: typedef*/ + +// PACKAGE +#include "FaserActsGeometryInterfaces/IFaserActsMaterialJsonWriterTool.h" + +// ACTS +#include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Plugins/Json/JsonGeometryConverter.hpp" +#include "FaserActsGeometry/FaserActsJsonGeometryConverter.h" + +namespace Acts { + class TrackingGeometry; +} + +class FaserActsMaterialJsonWriterTool : public extends<AthAlgTool, IFaserActsMaterialJsonWriterTool> +{ + +public: + + virtual StatusCode initialize() override; + + FaserActsMaterialJsonWriterTool(const std::string& type, const std::string& name, + const IInterface* parent); + virtual ~FaserActsMaterialJsonWriterTool() = default; + + virtual + void + write(const Acts::FaserActsJsonGeometryConverter::DetectorMaterialMaps& detMaterial) const override; + + virtual + void + write(const Acts::TrackingGeometry& tGeometry) const override; + + +private: + +Acts::FaserActsJsonGeometryConverter::Config m_cfg; + + Gaudi::Property<std::string> m_filePath{this, "OutputFile", "material-maps.json", "Output json file for the Material Map"}; + Gaudi::Property<bool> m_processSensitives{this, "processSensitives", true, "Write sensitive surface to the json file"}; + Gaudi::Property<bool> m_processApproaches{this, "processApproaches", true, "Write approche surface to the json file"}; + Gaudi::Property<bool> m_processRepresenting{this, "processRepresenting", true, "Write representing surface to the json file"}; + Gaudi::Property<bool> m_processBoundaries{this, "processBoundaries", true, "Write boundary surface to the json file"}; + Gaudi::Property<bool> m_processVolumes{this, "processVolumes", true, "Write volume to the json file"}; + Gaudi::Property<bool> m_processDenseVolumes{this, "processDenseVolumes", false, "Write dense volume to the json file"}; + Gaudi::Property<bool> m_processnonmaterial{this, "processnonmaterial", false, "Add proto material to all surfaces and volumes"}; +}; + +#endif diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsMaterialMapping.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsMaterialMapping.h new file mode 100644 index 00000000..bdeb9a7b --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsMaterialMapping.h @@ -0,0 +1,74 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ACTSMATERIALMAPPING_H +#define ACTSMATERIALMAPPING_H + +// ATHENA +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "GaudiKernel/ToolHandle.h" +#include "GaudiKernel/ServiceHandle.h" +#include "Gaudi/Property.h" /*no forward decl: typedef*/ +#include "GaudiKernel/ISvcLocator.h" +#include "StoreGate/ReadHandleKey.h" +#include "TrkGeometry/MaterialStepCollection.h" + +// ACTS +#include "Acts/EventData/TrackParameters.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Utilities/Helpers.hpp" +#include "Acts/Material/SurfaceMaterialMapper.hpp" +#include "Acts/Material/VolumeMaterialMapper.hpp" +// PACKAGE +#include "ActsGeometryInterfaces/IActsMaterialTrackWriterSvc.h" +#include "ActsGeometryInterfaces/IActsMaterialStepConverterTool.h" +#include "FaserActsGeometryInterfaces/IFaserActsSurfaceMappingTool.h" +#include "FaserActsGeometryInterfaces/IFaserActsVolumeMappingTool.h" +#include "FaserActsGeometryInterfaces/IFaserActsMaterialJsonWriterTool.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" + +// STL +#include <memory> +#include <vector> +#include <fstream> +#include <mutex> + +namespace Acts { + class ISurfaceMaterial; + class IVolumeMaterial; + + using SurfaceMaterialMap + = std::map<GeometryIdentifier, std::shared_ptr<const ISurfaceMaterial>>; + + using VolumeMaterialMap + = std::map<GeometryIdentifier, std::shared_ptr<const IVolumeMaterial>>; + + using DetectorMaterialMaps = std::pair<SurfaceMaterialMap, VolumeMaterialMap>; +} + + +class FaserActsMaterialMapping : public AthReentrantAlgorithm { +public: + FaserActsMaterialMapping (const std::string& name, ISvcLocator* pSvcLocator); + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& ctx) const override; + virtual StatusCode finalize() override; + +private: + ServiceHandle<IActsMaterialTrackWriterSvc> m_materialTrackWriterSvc; + Gaudi::Property<bool> m_mapSurfaces{this, "mapSurfaces", true, "Map the material onto surfaces"}; + Gaudi::Property<bool> m_mapVolumes{this, "mapVolumes", true, "Map the material onto volumes"}; + ToolHandle<IActsMaterialStepConverterTool> m_materialStepConverterTool{this, "MaterialStepConverterTool", "ActsMaterialStepConverterTool"}; + SG::ReadHandleKey<Trk::MaterialStepCollection> m_inputMaterialStepCollection; + ToolHandle<IFaserActsSurfaceMappingTool> m_surfaceMappingTool{this, "SurfaceMappingTool", "FaserActsSurfaceMappingTool"}; + ToolHandle<IFaserActsVolumeMappingTool> m_volumeMappingTool{this, "VolumeMappingTool", "FaserActsVolumeMappingTool"}; + ToolHandle<IFaserActsMaterialJsonWriterTool> m_materialJsonWriterTool{this, "MaterialJsonWriterTool", "FaserActsMaterialJsonWriterTool"}; + + Acts::MagneticFieldContext m_mctx; + Acts::GeometryContext m_gctx; + Acts::SurfaceMaterialMapper::State m_mappingState; + Acts::VolumeMaterialMapper::State m_mappingStateVol; +}; + +#endif // ActsGeometry_ActsExtrapolation_h \ No newline at end of file diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsSurfaceMappingTool.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsSurfaceMappingTool.h new file mode 100644 index 00000000..6dab4848 --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsSurfaceMappingTool.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef FASERACTSGEOMETRY_FASERACTSSURFACEMAPPINGTOOL_H +#define FASERACTSGEOMETRY_FASERACTSSURFACEMAPPINGTOOL_H + +// ATHENA +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/ServiceHandle.h" +#include "Gaudi/Property.h" +#include "GaudiKernel/EventContext.h" + +// PACKAGE +#include "FaserActsGeometryInterfaces/IFaserActsSurfaceMappingTool.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" + + +// ACTS +#include "Acts/Material/SurfaceMaterialMapper.hpp" + +// BOOST +#include <cmath> + +class FaserActsSurfaceMappingTool : public extends<AthAlgTool, IFaserActsSurfaceMappingTool> +{ + +public: + virtual StatusCode initialize() override; + + FaserActsSurfaceMappingTool(const std::string& type, const std::string& name, + const IInterface* parent); + + virtual + std::shared_ptr<Acts::SurfaceMaterialMapper> + mapper() const override + { + return m_mapper; + }; + + virtual + Acts::SurfaceMaterialMapper::State + mappingState() const override; + + virtual + const IFaserActsTrackingGeometryTool* + trackingGeometryTool() const override + { + return m_trackingGeometryTool.get(); + } + + +private: + // Straight line stepper + Acts::MagneticFieldContext m_magFieldContext; + Acts::GeometryContext m_geoContext; + using SlStepper = Acts::StraightLineStepper; + using StraightLinePropagator = Acts::Propagator<SlStepper, Acts::Navigator>; + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool{this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; + std::shared_ptr<Acts::SurfaceMaterialMapper> m_mapper; + std::shared_ptr<const Acts::TrackingGeometry> m_trackingGeometry; +}; + +#endif \ No newline at end of file diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsVolumeMappingTool.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsVolumeMappingTool.h new file mode 100644 index 00000000..699509d3 --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsVolumeMappingTool.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ACTSGEOMETRY_ACTSVOLUMEMAPPINGTOOL_H +#define ACTSGEOMETRY_ACTSVOLUMEMAPPINGTOOL_H + +// ATHENA +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/ServiceHandle.h" +#include "Gaudi/Property.h" +#include "GaudiKernel/EventContext.h" + +// PACKAGE +#include "FaserActsGeometryInterfaces/IFaserActsVolumeMappingTool.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" + +// ACTS +#include "Acts/Material/VolumeMaterialMapper.hpp" + +// BOOST + +#include <cmath> + +class FaserActsVolumeMappingTool : public extends<AthAlgTool, IFaserActsVolumeMappingTool> +{ + +public: + virtual StatusCode initialize() override; + + FaserActsVolumeMappingTool(const std::string& type, const std::string& name, + const IInterface* parent); + + std::shared_ptr<Acts::VolumeMaterialMapper> + mapper() const override + { + return m_mapper; + }; + + virtual + Acts::VolumeMaterialMapper::State + mappingState() const override; + + virtual + const IFaserActsTrackingGeometryTool* + trackingGeometryTool() const override + { + return m_trackingGeometryTool.get(); + } + + +private: + // Straight line stepper + Acts::MagneticFieldContext m_magFieldContext; + Acts::GeometryContext m_geoContext; + using SlStepper = Acts::StraightLineStepper; + using StraightLinePropagator = Acts::Propagator<SlStepper, Acts::Navigator>; + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool{this, "TrackingGeometryTool", "ActsTrackingGeometryTool"}; + std::shared_ptr<Acts::VolumeMaterialMapper> m_mapper; + std::shared_ptr<const Acts::TrackingGeometry> m_trackingGeometry; +}; + + + +#endif diff --git a/Tracking/Acts/FaserActsGeometry/python/ActsGeometryConfig.py b/Tracking/Acts/FaserActsGeometry/python/ActsGeometryConfig.py new file mode 100644 index 00000000..84bfe224 --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/python/ActsGeometryConfig.py @@ -0,0 +1,166 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory +FaserActsWriteTrackingGeometry,FaserActsTrackingGeometrySvc,FaserActsTrackingGeometryTool,FaserActsSurfaceMappingTool,FaserActsVolumeMappingTool,FaserActsObjWriterTool,FaserActsAlignmentCondAlg = CompFactory.getComps("FaserActsWriteTrackingGeometry","FaserActsTrackingGeometrySvc","FaserActsTrackingGeometryTool","FaserActsSurfaceMappingTool","FaserActsVolumeMappingTool","FaserActsObjWriterTool","FaserActsAlignmentCondAlg") + + + +def ActsTrackingGeometrySvcCfg(configFlags, name = "ActsTrackingGeometrySvc" ) : + result = ComponentAccumulator() + actsTrackingGeometrySvc = FaserActsTrackingGeometrySvc(name = "FaserActsTrackingGeometrySvc", **kwargs) + + if configFlags.TrackingGeometry.MaterialSource == "Input": + actsTrackingGeometrySvc.UseMaterialMap = True + actsTrackingGeometrySvc.MaterialMapInputFile = "material-maps.json" + if configFlags.TrackingGeometry.MaterialSource.find(".json") != -1: + actsTrackingGeometrySvc.UseMaterialMap = True + actsTrackingGeometrySvc.MaterialMapInputFile = configFlags.TrackingGeometry.MaterialSource + result.addService(actsTrackingGeometrySvc) + return result + +def ActsPropStepRootWriterSvcCfg(configFlags, + name="ActsPropStepRootWriterSvc", + FilePath="propsteps.root", + TreeName="propsteps"): + result = ComponentAccumulator() + + ActsPropStepRootWriterSvc = CompFactory.ActsPropStepRootWriterSvc + svc = ActsPropStepRootWriterSvc(name=name, + FilePath=FilePath, + TreeName=TreeName) + + result.addService(svc) + + return result + +def ActsTrackingGeometryToolCfg(configFlags, name = "ActsTrackingGeometryTool" ) : + result = ComponentAccumulator() + from FaserActsGeometry.FaserActsWriteTrackingGeometryConfig import FaserActsTrackingGeometrySvcCfg + acc = FaserActsTrackingGeometrySvcCfg(configFlags) + result.merge(acc) +# Acts_ActsTrackingGeometryTool = CompFactory.ActsTrackingGeometryTool + actsTrackingGeometryTool = FaserActsTrackingGeometryTool("TrackingGeometryTool") + result.addPublicTool(actsTrackingGeometryTool) + + return result, actsTrackingGeometryTool + +def NominalAlignmentCondAlgCfg(configFlags, name = "NominalAlignmentCondAlg", **kwargs) : + result = ComponentAccumulator() + + acc = ActsTrackingGeometrySvcCfg(configFlags) + result.merge(acc) + + Acts_NominalAlignmentCondAlg = CompFactory.NominalAlignmentCondAlg + nominalAlignmentCondAlg = Acts_NominalAlignmentCondAlg(name, **kwargs) + result.addCondAlgo(nominalAlignmentCondAlg) + + return result + +def ActsAlignmentCondAlgCfg(configFlags, name = "ActsAlignmentCondAlg", **kwargs) : + result = ComponentAccumulator() + + acc = ActsTrackingGeometrySvcCfg(configFlags) + result.merge(acc) + + Acts_ActsAlignmentCondAlg = CompFactory.ActsAlignmentCondAlg + actsAlignmentCondAlg = Acts_ActsAlignmentCondAlg(name, **kwargs) + result.addCondAlgo(actsAlignmentCondAlg) + + return result + +from MagFieldServices.MagFieldServicesConfig import MagneticFieldSvcCfg +def ActsExtrapolationToolCfg(configFlags, name="ActsExtrapolationTool", **kwargs) : + result=ComponentAccumulator() + + acc = MagneticFieldSvcCfg(configFlags) + result.merge(acc) + + acc, actsTrackingGeometryTool = ActsTrackingGeometryToolCfg(configFlags) + result.merge(acc) + + Acts_ActsExtrapolationTool = CompFactory.ActsExtrapolationTool + actsExtrapolationTool = Acts_ActsExtrapolationTool(name, **kwargs) + result.addPublicTool(actsExtrapolationTool, primary=True) + return result + + +def ActsMaterialTrackWriterSvcCfg(name="ActsMaterialTrackWriterSvc", + FilePath="MaterialTracks_mapping.root", + TreeName="material-tracks") : + result = ComponentAccumulator() + + Acts_ActsMaterialTrackWriterSvc = CompFactory.ActsMaterialTrackWriterSvc + ActsMaterialTrackWriterSvc = Acts_ActsMaterialTrackWriterSvc(name, + FilePath=FilePath, + TreeName=TreeName) + + from AthenaCommon.Constants import INFO + ActsMaterialTrackWriterSvc.OutputLevel = INFO + result.addService(ActsMaterialTrackWriterSvc, primary=True) + return result + +def ActsMaterialStepConverterToolCfg(name = "ActsMaterialStepConverterTool" ) : + result=ComponentAccumulator() + + Acts_ActsMaterialStepConverterTool = CompFactory.ActsMaterialStepConverterTool + ActsMaterialStepConverterTool = Acts_ActsMaterialStepConverterTool(name) + + from AthenaCommon.Constants import INFO + ActsMaterialStepConverterTool.OutputLevel = INFO + + result.addPublicTool(ActsMaterialStepConverterTool, primary=True) + return result + +def ActsSurfaceMappingToolCfg(configFlags, name = "FaserActsSurfaceMappingTool" ) : + result=ComponentAccumulator() + + acc, actsTrackingGeometryTool = ActsTrackingGeometryToolCfg(configFlags) + result.merge(acc) + + Acts_ActsSurfaceMappingTool = CompFactory.FaserActsSurfaceMappingTool + ActsSurfaceMappingTool = Acts_ActsSurfaceMappingTool(name) + + from AthenaCommon.Constants import INFO + ActsSurfaceMappingTool.OutputLevel = INFO + + result.addPublicTool(ActsSurfaceMappingTool, primary=True) + return result + +def ActsVolumeMappingToolCfg(configFlags, name = "ActsVolumeMappingTool" ) : + result=ComponentAccumulator() + + acc, actsTrackingGeometryTool = ActsTrackingGeometryToolCfg(configFlags) + result.merge(acc) + + Acts_ActsVolumeMappingTool = CompFactory.FaserActsVolumeMappingTool + FaserActsVolumeMappingTool = Acts_ActsVolumeMappingTool(name) + + from AthenaCommon.Constants import INFO + FaserActsVolumeMappingTool.OutputLevel = INFO + + result.addPublicTool(FaserActsVolumeMappingTool, primary=True) + return result + +def ActsMaterialJsonWriterToolCfg(name= "ActsMaterialJsonWriterTool", **kwargs) : + result=ComponentAccumulator() + + Acts_ActsMaterialJsonWriterTool = CompFactory.ActsMaterialJsonWriterTool + ActsMaterialJsonWriterTool = Acts_ActsMaterialJsonWriterTool(name, **kwargs) + + from AthenaCommon.Constants import INFO + ActsMaterialJsonWriterTool.OutputLevel = INFO + + result.addPublicTool(ActsMaterialJsonWriterTool, primary=True) + return result + +def ActsObjWriterToolCfg(name= "ActsObjWriterTool", **kwargs) : + result=ComponentAccumulator() + + Acts_ActsObjWriterTool = CompFactory.ActsObjWriterTool + ActsObjWriterTool = Acts_ActsObjWriterTool(name, **kwargs) + + from AthenaCommon.Constants import INFO + ActsObjWriterTool.OutputLevel = INFO + + result.addPublicTool(ActsObjWriterTool, primary=True) + return result diff --git a/Tracking/Acts/FaserActsGeometry/python/FaserActsMaterialMapping_jobOptions.py b/Tracking/Acts/FaserActsGeometry/python/FaserActsMaterialMapping_jobOptions.py new file mode 100644 index 00000000..63f3a602 --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/python/FaserActsMaterialMapping_jobOptions.py @@ -0,0 +1,109 @@ +############################################################### +# +# Map material from a Geantino scan onto the surfaces and +# volumes of the detector to creat a material map. +# +############################################################### + + +########################################################################## +# start from scratch with component accumulator + +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory + +from FaserActsGeometry.ActsGeometryConfig import ActsMaterialStepConverterToolCfg +from FaserActsGeometry.ActsGeometryConfig import ActsSurfaceMappingToolCfg, ActsVolumeMappingToolCfg +from FaserActsGeometry.ActsGeometryConfig import ActsMaterialJsonWriterToolCfg + +from FaserActsGeometry.ActsGeometryConfig import ActsAlignmentCondAlgCfg +from FaserGeoModel.FaserGeoModelConfig import FaserGeometryCfg + +def ActsMaterialMappingCfg(configFlags, name = "FaserActsMaterialMapping", **kwargs): + result = ComponentAccumulator() + + MaterialStepConverterTool = ActsMaterialStepConverterToolCfg() + kwargs["MaterialStepConverterTool"] = MaterialStepConverterTool.getPrimary() + result.merge(MaterialStepConverterTool) + + ActsSurfaceMappingTool = ActsSurfaceMappingToolCfg(configFlags) + kwargs["SurfaceMappingTool"] = ActsSurfaceMappingTool.getPrimary() + result.merge(ActsSurfaceMappingTool) + + FaserActsVolumeMappingTool = ActsVolumeMappingToolCfg(configFlags) + kwargs["VolumeMappingTool"] = FaserActsVolumeMappingTool.getPrimary() + result.merge(FaserActsVolumeMappingTool) + + ActsMaterialJsonWriterTool = ActsMaterialJsonWriterToolCfg(OutputFile = "material-maps.json", + processSensitives = False, + processnonmaterial = False) + + kwargs["MaterialJsonWriterTool"] = ActsMaterialJsonWriterTool.getPrimary() + result.merge(ActsMaterialJsonWriterTool) + + FaserActsMaterialMapping = CompFactory.FaserActsMaterialMapping + alg = FaserActsMaterialMapping(name, **kwargs) + result.addEventAlgo(alg) + + return result + +if "__main__" == __name__: + from AthenaCommon.Configurable import Configurable + from AthenaCommon.Logging import log + from AthenaCommon.Constants import VERBOSE, INFO + from CalypsoConfiguration.AllConfigFlags import ConfigFlags + from CalypsoConfiguration.MainServicesConfig import MainServicesCfg + from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg + from FaserActsGeometry.ActsGeometryConfig import ActsMaterialTrackWriterSvcCfg + Configurable.configurableRun3Behavior = True + + ## Just enable ID for the moment. + ConfigFlags.Input.isMC = True + ConfigFlags.Beam.Type = "collisions" + ConfigFlags.GeoModel.FaserVersion = "FASER-01" + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-XXXX-XXX-XX" +# ConfigFlags.Detector.SimulateBpipe = False +# ConfigFlags.Detector.SimulateID = False +# ConfigFlags.Detector.GeometryBpipe = True +# ConfigFlags.Detector.GeometryID = True +# ConfigFlags.Detector.GeometryPixel = True +# ConfigFlags.Detector.GeometrySCT = True +# ConfigFlags.Detector.GeometryCalo = True +# ConfigFlags.Detector.GeometryMuon = False +# ConfigFlags.Detector.GeometryTRT = True + ConfigFlags.TrackingGeometry.MaterialSource = "geometry-maps.json" + ConfigFlags.Concurrency.NumThreads = 1 + ConfigFlags.Concurrency.NumConcurrentEvents = 1 + + ConfigFlags.lock() + ConfigFlags.dump() + + cfg = MainServicesCfg(ConfigFlags) + + cfg.merge(FaserGeometryCfg(ConfigFlags)) + cfg.merge(ActsMaterialTrackWriterSvcCfg("ActsMaterialTrackWriterSvc", + "MaterialTracks_mapping.root")) + + cfg.merge(PoolReadCfg(ConfigFlags)) + eventSelector = cfg.getService("EventSelector") + eventSelector.InputCollections = ["MaterialStepCollection.root"] + +# from BeamPipeGeoModel.BeamPipeGMConfig import BeamPipeGeometryCfg +# cfg.merge(BeamPipeGeometryCfg(ConfigFlags)) + +# alignCondAlgCfg = ActsAlignmentCondAlgCfg(ConfigFlags) + +# cfg.merge(alignCondAlgCfg) + + alg = ActsMaterialMappingCfg(ConfigFlags, + OutputLevel=INFO, + mapSurfaces = True, + mapVolumes = True) + + cfg.merge(alg) + + cfg.printConfig() + + log.info("CONFIG DONE") + + cfg.run(80000) diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsJsonGeometryConverter.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsJsonGeometryConverter.cxx new file mode 100644 index 00000000..1984993b --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsJsonGeometryConverter.cxx @@ -0,0 +1,1069 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2017-2019 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "FaserActsGeometry/FaserActsJsonGeometryConverter.h" + +#include "Acts/Geometry/ApproachDescriptor.hpp" +#include "Acts/Geometry/CuboidVolumeBounds.hpp" +#include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp" +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Material/BinnedSurfaceMaterial.hpp" +#include "Acts/Material/HomogeneousSurfaceMaterial.hpp" +#include "Acts/Material/HomogeneousVolumeMaterial.hpp" +#include "Acts/Material/InterpolatedMaterialMap.hpp" +#include "Acts/Material/MaterialGridHelper.hpp" +#include "Acts/Material/ProtoSurfaceMaterial.hpp" +#include "Acts/Material/ProtoVolumeMaterial.hpp" +#include "Acts/Surfaces/RectangleBounds.hpp" +#include "Acts/Surfaces/SurfaceArray.hpp" +#include "Acts/Utilities/BinUtility.hpp" +#include "Acts/Utilities/BinningType.hpp" +#include <Acts/Surfaces/AnnulusBounds.hpp> +#include <Acts/Surfaces/CylinderBounds.hpp> +#include <Acts/Surfaces/RadialBounds.hpp> +#include <Acts/Surfaces/SurfaceBounds.hpp> + +#include <cstdio> +#include <fstream> +#include <iostream> +#include <map> +#include <sstream> +#include <stdexcept> +#include <string> + +#include <boost/algorithm/string.hpp> +#include <boost/algorithm/string/finder.hpp> +#include <boost/algorithm/string/iter_find.hpp> + +namespace { + +using json = nlohmann::json; + +// helper functions to encode/decode indefinite material +// +// encoded either as `null` for vacuum or to an array of material parameters + +json encodeMaterial(const Acts::Material& material) { + if (!material) { + return nullptr; + } + json encoded = json::array(); + for (unsigned i = 0; i < material.parameters().size(); ++i) { + encoded.push_back(material.parameters()[i]); + } + return encoded; +} + +Acts::Material decodeMaterial(const json& encoded) { + if (encoded.is_null()) { + return {}; + } + Acts::Material::ParametersVector params = + Acts::Material::ParametersVector::Zero(); + for (auto i = params.size(); 0 < i--;) { + // .at(...) ensures bound checks + params[i] = encoded.at(i); + } + return Acts::Material(params); +} + +// helper functions to encode/decode concrete material slabs +// +// encoded as an object w/ two entries: `material` and `thickness` + +json encodeMaterialSlab(const Acts::MaterialSlab& slab) { + return { + {"material", encodeMaterial(slab.material())}, + {"thickness", slab.thickness()}, + }; +} + +Acts::MaterialSlab decodeMaterialSlab(const json& encoded) { + return Acts::MaterialSlab(decodeMaterial(encoded.at("material")), + encoded.at("thickness").get<float>()); +} + +} // namespace + +Acts::FaserActsJsonGeometryConverter::FaserActsJsonGeometryConverter( + const Acts::FaserActsJsonGeometryConverter::Config& cfg) + : m_cfg(std::move(cfg)) { + // Validate the configuration + if (!m_cfg.logger) { + throw std::invalid_argument("Missing logger"); + } +} + +std::pair<std::map<Acts::GeometryIdentifier, + std::shared_ptr<const Acts::ISurfaceMaterial>>, + std::map<Acts::GeometryIdentifier, + std::shared_ptr<const Acts::IVolumeMaterial>>> +Acts::FaserActsJsonGeometryConverter::jsonToMaterialMaps(const json& materialmaps) { + auto& j = materialmaps; + // The return maps + std::pair<SurfaceMaterialMap, VolumeMaterialMap> maps; + ACTS_VERBOSE("j2a: Reading material maps from json file."); + ACTS_VERBOSE("j2a: Found entries for " << j.count(m_cfg.volkey) + << " volume(s)."); + // Structured binding + for (auto& [key, value] : j.items()) { + // Check if this the volume key + if (key == m_cfg.volkey) { + // Get the volume json + auto volj = value; + for (auto& [vkey, vvalue] : volj.items()) { + // Create the volume id + int vid = std::stoi(vkey); + Acts::GeometryIdentifier volumeID; + volumeID.setVolume(vid); + ACTS_VERBOSE("j2a: -> Found Volume " << vid); + // Loop through the information in the volume + for (auto& [vckey, vcvalue] : vvalue.items()) { + if (vckey == m_cfg.boukey and m_cfg.processBoundaries and + not vcvalue.empty()) { + ACTS_VERBOSE("j2a: --> BoundarySurface(s) to be parsed"); + for (auto& [bkey, bvalue] : vcvalue.items()) { + // Create the boundary id + int bid = std::stoi(bkey); + Acts::GeometryIdentifier boundaryID(volumeID); + boundaryID.setBoundary(bid); + ACTS_VERBOSE("j2a: ---> Found boundary surface " << bid); + if (bvalue[m_cfg.mapkey] == true) { + auto boumat = jsonToSurfaceMaterial(bvalue); + maps.first[boundaryID] = + std::shared_ptr<const ISurfaceMaterial>(boumat); + } + } + } else if (vckey == m_cfg.laykey) { + ACTS_VERBOSE("j2a: --> Layer(s) to be parsed"); + // Loop over layers and repeat + auto layj = vcvalue; + for (auto& [lkey, lvalue] : layj.items()) { + // Create the layer id + int lid = std::stoi(lkey); + Acts::GeometryIdentifier layerID(volumeID); + layerID.setLayer(lid); + ACTS_VERBOSE("j2a: ---> Found Layer " << lid); + // Finally loop over layer components + for (auto& [lckey, lcvalue] : lvalue.items()) { + if (lckey == m_cfg.repkey and m_cfg.processRepresenting and + not lcvalue.empty()) { + ACTS_VERBOSE("j2a: ----> Found representing surface"); + if (lcvalue[m_cfg.mapkey] == true) { + auto repmat = jsonToSurfaceMaterial(lcvalue); + maps.first[layerID] = + std::shared_ptr<const Acts::ISurfaceMaterial>(repmat); + } + } else if (lckey == m_cfg.appkey and m_cfg.processApproaches and + not lcvalue.empty()) { + ACTS_VERBOSE("j2a: ----> Found approach surface(s)"); + // Loop over approach surfaces + for (auto& [askey, asvalue] : lcvalue.items()) { + // Create the layer id, todo set to max value + int aid = (askey == "*") ? 0 : std::stoi(askey); + Acts::GeometryIdentifier approachID(layerID); + approachID.setApproach(aid); + ACTS_VERBOSE("j2a: -----> Approach surface " << askey); + if (asvalue[m_cfg.mapkey] == true) { + auto appmat = jsonToSurfaceMaterial(asvalue); + maps.first[approachID] = + std::shared_ptr<const Acts::ISurfaceMaterial>(appmat); + } + } + } else if (lckey == m_cfg.senkey and m_cfg.processSensitives and + not lcvalue.empty()) { + ACTS_VERBOSE("j2a: ----> Found sensitive surface(s)"); + // Loop over sensitive surfaces + for (auto& [sskey, ssvalue] : lcvalue.items()) { + // Create the layer id, todo set to max value + int sid = (sskey == "*") ? 0 : std::stoi(sskey); + Acts::GeometryIdentifier senisitiveID(layerID); + senisitiveID.setSensitive(sid); + ACTS_VERBOSE("j2a: -----> Sensitive surface " << sskey); + if (ssvalue[m_cfg.mapkey] == true) { + auto senmat = jsonToSurfaceMaterial(ssvalue); + maps.first[senisitiveID] = + std::shared_ptr<const Acts::ISurfaceMaterial>(senmat); + } + } + } + } + } + + } else if (m_cfg.processVolumes and vckey == m_cfg.matkey and + not vcvalue.empty()) { + ACTS_VERBOSE("--> VolumeMaterial to be parsed"); + if (vcvalue[m_cfg.mapkey] == true) { + auto intermat = jsonToVolumeMaterial(vcvalue); + maps.second[volumeID] = + std::shared_ptr<const Acts::IVolumeMaterial>(intermat); + } + } + } + } + } else if (key == m_cfg.geoversion) { + ACTS_VERBOSE("Detector version: " << m_cfg.geoversion); + } + } + + // Return the filled maps + return maps; +} + +/// Convert method +/// +json Acts::FaserActsJsonGeometryConverter::materialMapsToJson( + const DetectorMaterialMaps& maps) { + DetectorRep detRep; + // Collect all GeometryIdentifiers per VolumeID for the formatted output + for (auto& [key, value] : maps.first) { + geo_id_value vid = key.volume(); + auto volRep = detRep.volumes.find(vid); + if (volRep == detRep.volumes.end()) { + detRep.volumes.insert({vid, VolumeRep()}); + volRep = detRep.volumes.find(vid); + volRep->second.volumeID = key; + } + geo_id_value lid = key.layer(); + if (lid != 0) { + // we are on a layer, get the layer rep + auto layRep = volRep->second.layers.find(lid); + if (layRep == volRep->second.layers.end()) { + volRep->second.layers.insert({lid, LayerRep()}); + layRep = volRep->second.layers.find(lid); + layRep->second.layerID = key; + } + // now insert appropriately + geo_id_value sid = key.sensitive(); + geo_id_value aid = key.approach(); + if (sid != 0) { + layRep->second.sensitives.insert({sid, value.get()}); + } else if (aid != 0) { + layRep->second.approaches.insert({aid, value.get()}); + } else { + layRep->second.representing = value.get(); + } + + } else { + // not on a layer can only be a boundary surface + geo_id_value bid = key.boundary(); + volRep->second.boundaries.insert({bid, value.get()}); + } + } + for (auto& [key, value] : maps.second) { + // find the volume representation + geo_id_value vid = key.volume(); + auto volRep = detRep.volumes.find(vid); + if (volRep == detRep.volumes.end()) { + detRep.volumes.insert({vid, VolumeRep()}); + volRep = detRep.volumes.find(vid); + volRep->second.volumeID = key; + } + volRep->second.material = value.get(); + } + // convert the detector representation to json format + return detectorRepToJson(detRep); +} + +/// Create Json from a detector represenation +json Acts::FaserActsJsonGeometryConverter::detectorRepToJson(const DetectorRep& detRep) { + json detectorj; + ACTS_VERBOSE("a2j: Writing json from detector representation"); + ACTS_VERBOSE("a2j: Found entries for " << detRep.volumes.size() + << " volume(s)."); + + json volumesj; + for (auto& [key, value] : detRep.volumes) { + json volj; + ACTS_VERBOSE("a2j: -> Writing Volume: " << key); + volj[m_cfg.namekey] = value.volumeName; + std::ostringstream svolumeID; + svolumeID << value.volumeID; + volj[m_cfg.geometryidkey] = svolumeID.str(); + if (m_cfg.processVolumes && value.material) { + volj[m_cfg.matkey] = volumeMaterialToJson(*value.material); + } + // Write the layers + if (not value.layers.empty()) { + ACTS_VERBOSE("a2j: ---> Found " << value.layers.size() << " layer(s) "); + json layersj; + for (auto& [lkey, lvalue] : value.layers) { + ACTS_VERBOSE("a2j: ----> Convert layer " << lkey); + json layj; + std::ostringstream slayerID; + slayerID << lvalue.layerID; + layj[m_cfg.geometryidkey] = slayerID.str(); + // First check for approaches + if (not lvalue.approaches.empty() and m_cfg.processApproaches) { + ACTS_VERBOSE("a2j: -----> Found " << lvalue.approaches.size() + << " approach surface(s)"); + json approachesj; + for (auto& [akey, avalue] : lvalue.approaches) { + ACTS_VERBOSE("a2j: ------> Convert approach surface " << akey); + approachesj[std::to_string(akey)] = surfaceMaterialToJson(*avalue); + if (lvalue.approacheSurfaces.find(akey) != + lvalue.approacheSurfaces.end()) + addSurfaceToJson(approachesj[std::to_string(akey)], + lvalue.approacheSurfaces.at(akey)); + } + // Add to the layer json + layj[m_cfg.appkey] = approachesj; + } + // Then check for sensitive + if (not lvalue.sensitives.empty() and m_cfg.processSensitives) { + ACTS_VERBOSE("a2j: -----> Found " << lvalue.sensitives.size() + << " sensitive surface(s)"); + json sensitivesj; + for (auto& [skey, svalue] : lvalue.sensitives) { + ACTS_VERBOSE("a2j: ------> Convert sensitive surface " << skey); + sensitivesj[std::to_string(skey)] = surfaceMaterialToJson(*svalue); + if (lvalue.sensitiveSurfaces.find(skey) != + lvalue.sensitiveSurfaces.end()) + addSurfaceToJson(sensitivesj[std::to_string(skey)], + lvalue.sensitiveSurfaces.at(skey)); + } + // Add to the layer json + layj[m_cfg.senkey] = sensitivesj; + } + // Finally check for representing + if (lvalue.representing != nullptr and m_cfg.processRepresenting) { + ACTS_VERBOSE("a2j: ------> Convert representing surface "); + layj[m_cfg.repkey] = surfaceMaterialToJson(*lvalue.representing); + if (lvalue.representingSurface != nullptr) + addSurfaceToJson(layj[m_cfg.repkey], lvalue.representingSurface); + } + layersj[std::to_string(lkey)] = layj; + } + volj[m_cfg.laykey] = layersj; + } + // Write the boundary surfaces + if (not value.boundaries.empty()) { + ACTS_VERBOSE("a2j: ---> Found " << value.boundaries.size() + << " boundary/ies "); + json boundariesj; + for (auto& [bkey, bvalue] : value.boundaries) { + ACTS_VERBOSE("a2j: ----> Convert boundary " << bkey); + boundariesj[std::to_string(bkey)] = surfaceMaterialToJson(*bvalue); + if (value.boundarySurfaces.find(bkey) != value.boundarySurfaces.end()) + addSurfaceToJson(boundariesj[std::to_string(bkey)], + value.boundarySurfaces.at(bkey)); + } + volj[m_cfg.boukey] = boundariesj; + } + + volumesj[std::to_string(key)] = volj; + } + // Assign the volume json to the detector json + detectorj[m_cfg.volkey] = volumesj; + + return detectorj; +} + +/// Create the Surface Material +const Acts::ISurfaceMaterial* +Acts::FaserActsJsonGeometryConverter::jsonToSurfaceMaterial(const json& material) { + Acts::ISurfaceMaterial* sMaterial = nullptr; + // The bin utility for deescribing the data + Acts::BinUtility bUtility; + for (auto& [key, value] : material.items()) { + if (key == m_cfg.transfokeys and not value.empty()) { + bUtility = Acts::BinUtility(jsonToTransform(value)); + break; + } + } + // Convert the material + Acts::MaterialSlabMatrix mpMatrix; + // Structured binding + for (auto& [key, value] : material.items()) { + // Check json keys + if (key == m_cfg.bin0key and not value.empty()) { + bUtility += jsonToBinUtility(value); + } else if (key == m_cfg.bin1key and not value.empty()) { + bUtility += jsonToBinUtility(value); + } + if (key == m_cfg.datakey and not value.empty()) { + mpMatrix = jsonToMaterialMatrix(value); + } + } + + // We have protoMaterial + if (mpMatrix.empty()) { + sMaterial = new Acts::ProtoSurfaceMaterial(bUtility); + } else if (bUtility.bins() == 1) { + sMaterial = new Acts::HomogeneousSurfaceMaterial(mpMatrix[0][0]); + } else { + sMaterial = new Acts::BinnedSurfaceMaterial(bUtility, mpMatrix); + } + // return what you have + return sMaterial; +} + +/// Create the Volume Material +const Acts::IVolumeMaterial* Acts::FaserActsJsonGeometryConverter::jsonToVolumeMaterial( + const json& material) { + Acts::IVolumeMaterial* vMaterial = nullptr; + // The bin utility for deescribing the data + Acts::BinUtility bUtility; + for (auto& [key, value] : material.items()) { + if (key == m_cfg.transfokeys and not value.empty()) { + bUtility = Acts::BinUtility(jsonToTransform(value)); + break; + } + } + // Convert the material + std::vector<Material> mmat; + // Structured binding + for (auto& [key, value] : material.items()) { + // Check json keys + if (key == m_cfg.bin0key and not value.empty()) { + bUtility += jsonToBinUtility(value); + } else if (key == m_cfg.bin1key and not value.empty()) { + bUtility += jsonToBinUtility(value); + } else if (key == m_cfg.bin2key and not value.empty()) { + bUtility += jsonToBinUtility(value); + } + if (key == m_cfg.datakey and not value.empty()) { + for (const auto& bin : value) { + mmat.push_back(decodeMaterial(bin)); + } + } + } + + // We have protoMaterial + if (mmat.empty()) { + vMaterial = new Acts::ProtoVolumeMaterial(bUtility); + } else if (mmat.size() == 1) { + vMaterial = new Acts::HomogeneousVolumeMaterial(mmat[0]); + } else { + if (bUtility.dimensions() == 2) { + std::function<Acts::Vector2D(Acts::Vector3D)> transfoGlobalToLocal; + Acts::Grid2D grid = createGrid2D(bUtility, transfoGlobalToLocal); + + Acts::Grid2D::point_t min = grid.minPosition(); + Acts::Grid2D::point_t max = grid.maxPosition(); + Acts::Grid2D::index_t nBins = grid.numLocalBins(); + + Acts::EAxis axis1(min[0], max[0], nBins[0]); + Acts::EAxis axis2(min[1], max[1], nBins[1]); + + // Build the grid and fill it with data + MaterialGrid2D mGrid(std::make_tuple(axis1, axis2)); + + for (size_t bin = 0; bin < mmat.size(); bin++) { + mGrid.at(bin) = mmat[bin].parameters(); + } + MaterialMapper<MaterialGrid2D> matMap(transfoGlobalToLocal, mGrid); + vMaterial = + new Acts::InterpolatedMaterialMap<MaterialMapper<MaterialGrid2D>>( + std::move(matMap), bUtility); + } else if (bUtility.dimensions() == 3) { + std::function<Acts::Vector3D(Acts::Vector3D)> transfoGlobalToLocal; + Acts::Grid3D grid = createGrid3D(bUtility, transfoGlobalToLocal); + + Acts::Grid3D::point_t min = grid.minPosition(); + Acts::Grid3D::point_t max = grid.maxPosition(); + Acts::Grid3D::index_t nBins = grid.numLocalBins(); + + Acts::EAxis axis1(min[0], max[0], nBins[0]); + Acts::EAxis axis2(min[1], max[1], nBins[1]); + Acts::EAxis axis3(min[2], max[2], nBins[2]); + + // Build the grid and fill it with data + MaterialGrid3D mGrid(std::make_tuple(axis1, axis2, axis3)); + + for (size_t bin = 0; bin < mmat.size(); bin++) { + mGrid.at(bin) = mmat[bin].parameters(); + } + MaterialMapper<MaterialGrid3D> matMap(transfoGlobalToLocal, mGrid); + vMaterial = + new Acts::InterpolatedMaterialMap<MaterialMapper<MaterialGrid3D>>( + std::move(matMap), bUtility); + } + } + // return what you have + return vMaterial; +} + +json Acts::FaserActsJsonGeometryConverter::trackingGeometryToJson( + const Acts::TrackingGeometry& tGeometry) { + DetectorRep detRep; + convertToRep(detRep, *tGeometry.highestTrackingVolume()); + return detectorRepToJson(detRep); +} + +void Acts::FaserActsJsonGeometryConverter::convertToRep( + DetectorRep& detRep, const Acts::TrackingVolume& tVolume) { + // The writer reader volume representation + VolumeRep volRep; + volRep.volumeName = tVolume.volumeName(); + // there are confined volumes + if (tVolume.confinedVolumes() != nullptr) { + // get through the volumes + auto& volumes = tVolume.confinedVolumes()->arrayObjects(); + // loop over the volumes + for (auto& vol : volumes) { + // recursive call + convertToRep(detRep, *vol); + } + } + // there are dense volumes + if (m_cfg.processDenseVolumes && !tVolume.denseVolumes().empty()) { + // loop over the volumes + for (auto& vol : tVolume.denseVolumes()) { + // recursive call + convertToRep(detRep, *vol); + } + } + // Get the volume Id + Acts::GeometryIdentifier volumeID = tVolume.geometryId(); + geo_id_value vid = volumeID.volume(); + + // Write the material if there's one + if (tVolume.volumeMaterial() != nullptr) { + volRep.material = tVolume.volumeMaterial(); + } else if (m_cfg.processnonmaterial == true) { + Acts::BinUtility bUtility = DefaultBin(tVolume); + Acts::IVolumeMaterial* bMaterial = new Acts::ProtoVolumeMaterial(bUtility); + volRep.material = bMaterial; + } + // there are confied layers + if (tVolume.confinedLayers() != nullptr) { + // get the layers + auto& layers = tVolume.confinedLayers()->arrayObjects(); + // loop of the volumes + for (auto& lay : layers) { + auto layRep = convertToRep(*lay); + if (layRep) { + // it's a valid representation so let's go with it + Acts::GeometryIdentifier layerID = lay->geometryId(); + geo_id_value lid = layerID.layer(); + volRep.layers.insert({lid, std::move(layRep)}); + } + } + } + // Let's finally check the boundaries + for (auto& bsurf : tVolume.boundarySurfaces()) { + // the surface representation + auto& bssfRep = bsurf->surfaceRepresentation(); + if (bssfRep.surfaceMaterial() != nullptr) { + Acts::GeometryIdentifier boundaryID = bssfRep.geometryId(); + geo_id_value bid = boundaryID.boundary(); + // Ignore if the volumeID is not correct (i.e. shared boundary) + // if (boundaryID.value(Acts::GeometryIdentifier::volume_mask) == vid){ + volRep.boundaries[bid] = bssfRep.surfaceMaterial(); + volRep.boundarySurfaces[bid] = &bssfRep; + // } + } else if (m_cfg.processnonmaterial == true) { + // if no material suface exist add a default one for the mapping + // configuration + Acts::GeometryIdentifier boundaryID = bssfRep.geometryId(); + geo_id_value bid = boundaryID.boundary(); + Acts::BinUtility bUtility = DefaultBin(bssfRep); + Acts::ISurfaceMaterial* bMaterial = + new Acts::ProtoSurfaceMaterial(bUtility); + volRep.boundaries[bid] = bMaterial; + volRep.boundarySurfaces[bid] = &bssfRep; + } + } + // Write if it's good + if (volRep) { + volRep.volumeName = tVolume.volumeName(); + volRep.volumeID = volumeID; + detRep.volumes.insert({vid, std::move(volRep)}); + } + return; +} + +Acts::FaserActsJsonGeometryConverter::LayerRep Acts::FaserActsJsonGeometryConverter::convertToRep( + const Acts::Layer& tLayer) { + LayerRep layRep; + // fill layer ID information + layRep.layerID = tLayer.geometryId(); + if (m_cfg.processSensitives and tLayer.surfaceArray() != nullptr) { + for (auto& ssf : tLayer.surfaceArray()->surfaces()) { + if (ssf != nullptr && ssf->surfaceMaterial() != nullptr) { + Acts::GeometryIdentifier sensitiveID = ssf->geometryId(); + geo_id_value sid = sensitiveID.sensitive(); + layRep.sensitives.insert({sid, ssf->surfaceMaterial()}); + layRep.sensitiveSurfaces.insert({sid, ssf}); + } else if (m_cfg.processnonmaterial == true) { + // if no material suface exist add a default one for the mapping + // configuration + Acts::GeometryIdentifier sensitiveID = ssf->geometryId(); + geo_id_value sid = sensitiveID.sensitive(); + Acts::BinUtility sUtility = DefaultBin(*ssf); + Acts::ISurfaceMaterial* sMaterial = + new Acts::ProtoSurfaceMaterial(sUtility); + layRep.sensitives.insert({sid, sMaterial}); + layRep.sensitiveSurfaces.insert({sid, ssf}); + } + } + } + // the representing + if (!(tLayer.surfaceRepresentation().geometryId() == GeometryIdentifier())) { + if (tLayer.surfaceRepresentation().surfaceMaterial() != nullptr) { + layRep.representing = tLayer.surfaceRepresentation().surfaceMaterial(); + layRep.representingSurface = &tLayer.surfaceRepresentation(); + } else if (m_cfg.processnonmaterial == true) { + // if no material suface exist add a default one for the mapping + // configuration + Acts::BinUtility rUtility = DefaultBin(tLayer.surfaceRepresentation()); + Acts::ISurfaceMaterial* rMaterial = + new Acts::ProtoSurfaceMaterial(rUtility); + layRep.representing = rMaterial; + layRep.representingSurface = &tLayer.surfaceRepresentation(); + } + } + // the approach + if (tLayer.approachDescriptor() != nullptr) { + for (auto& asf : tLayer.approachDescriptor()->containedSurfaces()) { + // get the surface and check for material + if (asf->surfaceMaterial() != nullptr) { + Acts::GeometryIdentifier approachID = asf->geometryId(); + geo_id_value aid = approachID.approach(); + layRep.approaches.insert({aid, asf->surfaceMaterial()}); + layRep.approacheSurfaces.insert({aid, asf}); + } else if (m_cfg.processnonmaterial == true) { + // if no material suface exist add a default one for the mapping + // configuration + Acts::GeometryIdentifier approachID = asf->geometryId(); + geo_id_value aid = approachID.approach(); + Acts::BinUtility aUtility = DefaultBin(*asf); + Acts::ISurfaceMaterial* aMaterial = + new Acts::ProtoSurfaceMaterial(aUtility); + layRep.approaches.insert({aid, aMaterial}); + layRep.approacheSurfaces.insert({aid, asf}); + } + } + } + // return the layer representation + return layRep; +} + +json Acts::FaserActsJsonGeometryConverter::surfaceMaterialToJson( + const Acts::ISurfaceMaterial& sMaterial) { + json smj; + // A bin utility needs to be written + const Acts::BinUtility* bUtility = nullptr; + // Check if we have a proto material + auto psMaterial = dynamic_cast<const Acts::ProtoSurfaceMaterial*>(&sMaterial); + if (psMaterial != nullptr) { + // Type is proto material + smj[m_cfg.typekey] = "proto"; + // by default the protoMaterial is not used for mapping + smj[m_cfg.mapkey] = false; + bUtility = &(psMaterial->binUtility()); + } else { + // Now check if we have a homogeneous material + auto hsMaterial = + dynamic_cast<const Acts::HomogeneousSurfaceMaterial*>(&sMaterial); + if (hsMaterial != nullptr) { + // type is homogeneous + smj[m_cfg.typekey] = "homogeneous"; + smj[m_cfg.mapkey] = true; + if (m_cfg.writeData) { + smj[m_cfg.datakey] = json::array({ + json::array({ + encodeMaterialSlab(hsMaterial->materialSlab(0, 0)), + }), + }); + } + } else { + // Only option remaining: BinnedSurface material + auto bsMaterial = + dynamic_cast<const Acts::BinnedSurfaceMaterial*>(&sMaterial); + if (bsMaterial != nullptr) { + // type is binned + smj[m_cfg.typekey] = "binned"; + smj[m_cfg.mapkey] = true; + bUtility = &(bsMaterial->binUtility()); + // convert the data + // get the material matrix + if (m_cfg.writeData) { + json mmat = json::array(); + for (const auto& mpVector : bsMaterial->fullMaterial()) { + json mvec = json::array(); + for (const auto& mp : mpVector) { + mvec.push_back(encodeMaterialSlab(mp)); + } + mmat.push_back(std::move(mvec)); + } + smj[m_cfg.datakey] = std::move(mmat); + } + } + } + } + // add the bin utility + if (bUtility != nullptr && !bUtility->binningData().empty()) { + std::vector<std::string> binkeys = {m_cfg.bin0key, m_cfg.bin1key}; + // loop over dimensions and write + auto& binningData = bUtility->binningData(); + // loop over the dimensions + for (size_t ibin = 0; ibin < binningData.size(); ++ibin) { + json binj; + auto cbData = binningData[ibin]; + binj.push_back(Acts::binningValueNames[cbData.binvalue]); + if (cbData.option == Acts::closed) { + binj.push_back("closed"); + } else { + binj.push_back("open"); + } + binj.push_back(cbData.bins()); + // If protoMaterial has a non uniform binning (non default) then it is + // used by default in the mapping + if (smj[m_cfg.typekey] == "proto" && cbData.bins() > 1) + smj[m_cfg.mapkey] = true; + // If it's not a proto map, write min / max + if (smj[m_cfg.typekey] != "proto") { + std::pair<double, double> minMax = {cbData.min, cbData.max}; + binj.push_back(minMax); + } + smj[binkeys[ibin]] = binj; + } + std::vector<double> transfo; + Acts::Transform3D transfo_matrix = bUtility->transform(); + if (not transfo_matrix.isApprox(Acts::Transform3D::Identity())) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + transfo.push_back(transfo_matrix(j, i)); + } + } + smj[m_cfg.transfokeys] = transfo; + } + } + return smj; +} + +json Acts::FaserActsJsonGeometryConverter::volumeMaterialToJson( + const Acts::IVolumeMaterial& vMaterial) { + json smj; + // A bin utility needs to be written + const Acts::BinUtility* bUtility = nullptr; + // Check if we have a proto material + auto pvMaterial = dynamic_cast<const Acts::ProtoVolumeMaterial*>(&vMaterial); + if (pvMaterial != nullptr) { + // Type is proto material + smj[m_cfg.typekey] = "proto"; + // by default the protoMaterial is not used for mapping + smj[m_cfg.mapkey] = false; + bUtility = &(pvMaterial->binUtility()); + } else { + // Now check if we have a homogeneous material + auto hvMaterial = + dynamic_cast<const Acts::HomogeneousVolumeMaterial*>(&vMaterial); + if (hvMaterial != nullptr) { + // type is homogeneous + smj[m_cfg.typekey] = "homogeneous"; + smj[m_cfg.mapkey] = true; + if (m_cfg.writeData) { + // array of encoded materials w/ one entry + smj[m_cfg.datakey] = json::array({ + encodeMaterial(hvMaterial->material({0, 0, 0})), + }); + } + } else { + // Only option remaining: material map + auto bvMaterial2D = dynamic_cast< + const Acts::InterpolatedMaterialMap<MaterialMapper<MaterialGrid2D>>*>( + &vMaterial); + // Now check if we have a 2D map + if (bvMaterial2D != nullptr) { + // type is binned + smj[m_cfg.typekey] = "interpolated2D"; + smj[m_cfg.mapkey] = true; + bUtility = &(bvMaterial2D->binUtility()); + // convert the data + if (m_cfg.writeData) { + json mmat = json::array(); + MaterialGrid2D grid = bvMaterial2D->getMapper().getGrid(); + for (size_t bin = 0; bin < grid.size(); bin++) { + mmat.push_back(encodeMaterial(grid.at(bin))); + } + smj[m_cfg.datakey] = std::move(mmat); + } + } else { + // Only option remaining: material map + auto bvMaterial3D = dynamic_cast<const Acts::InterpolatedMaterialMap< + MaterialMapper<MaterialGrid3D>>*>(&vMaterial); + // Now check if we have a 3D map + if (bvMaterial3D != nullptr) { + // type is binned + smj[m_cfg.typekey] = "interpolated3D"; + smj[m_cfg.mapkey] = true; + bUtility = &(bvMaterial3D->binUtility()); + // convert the data + if (m_cfg.writeData) { + json mmat = json::array(); + MaterialGrid3D grid = bvMaterial3D->getMapper().getGrid(); + for (size_t bin = 0; bin < grid.size(); bin++) { + mmat.push_back(encodeMaterial(grid.at(bin))); + } + smj[m_cfg.datakey] = std::move(mmat); + } + } + } + } + } + // add the bin utility + if (bUtility != nullptr && !bUtility->binningData().empty()) { + std::vector<std::string> binkeys = {m_cfg.bin0key, m_cfg.bin1key, + m_cfg.bin2key}; + // loop over dimensions and write + auto& binningData = bUtility->binningData(); + // loop over the dimensions + for (size_t ibin = 0; ibin < binningData.size(); ++ibin) { + json binj; + auto cbData = binningData[ibin]; + binj.push_back(Acts::binningValueNames[cbData.binvalue]); + if (cbData.option == Acts::closed) { + binj.push_back("closed"); + } else { + binj.push_back("open"); + } + binj.push_back(cbData.bins()); + // If protoMaterial has a non uniform binning (non default) then it is + // used by default in the mapping + if (smj[m_cfg.typekey] == "proto" && cbData.bins() > 1) + smj[m_cfg.mapkey] = true; + // If it's not a proto map, write min / max + if (smj[m_cfg.typekey] != "proto") { + std::pair<double, double> minMax = {cbData.min, cbData.max}; + binj.push_back(minMax); + } + smj[binkeys[ibin]] = binj; + } + std::vector<double> transfo; + Acts::Transform3D transfo_matrix = bUtility->transform(); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + transfo.push_back(transfo_matrix(j, i)); + } + } + smj[m_cfg.transfokeys] = transfo; + } + return smj; +} + +void Acts::FaserActsJsonGeometryConverter::addSurfaceToJson(json& sjson, + const Surface* surface) { + // Get the ID of the surface (redundant but help readability) + std::ostringstream SurfaceID; + SurfaceID << surface->geometryId(); + sjson[m_cfg.surfacegeometryidkey] = SurfaceID.str(); + + // Cast the surface bound to both disk and cylinder + const Acts::SurfaceBounds& surfaceBounds = surface->bounds(); + auto sTransform = surface->transform(GeometryContext()); + + const Acts::RadialBounds* radialBounds = + dynamic_cast<const Acts::RadialBounds*>(&surfaceBounds); + const Acts::CylinderBounds* cylinderBounds = + dynamic_cast<const Acts::CylinderBounds*>(&surfaceBounds); + const Acts::AnnulusBounds* annulusBounds = + dynamic_cast<const Acts::AnnulusBounds*>(&surfaceBounds); + + if (radialBounds != nullptr) { + sjson[m_cfg.surfacetypekey] = "Disk"; + sjson[m_cfg.surfacepositionkey] = sTransform.translation().z(); + sjson[m_cfg.surfacerangekey] = {radialBounds->rMin(), radialBounds->rMax()}; + } + if (cylinderBounds != nullptr) { + sjson[m_cfg.surfacetypekey] = "Cylinder"; + sjson[m_cfg.surfacepositionkey] = cylinderBounds->get(CylinderBounds::eR); + sjson[m_cfg.surfacerangekey] = { + -1 * cylinderBounds->get(CylinderBounds::eHalfLengthZ), + cylinderBounds->get(CylinderBounds::eHalfLengthZ)}; + } + if (annulusBounds != nullptr) { + sjson[m_cfg.surfacetypekey] = "Annulus"; + sjson[m_cfg.surfacepositionkey] = sTransform.translation().z(); + sjson[m_cfg.surfacerangekey] = { + {annulusBounds->rMin(), annulusBounds->rMax()}, + {annulusBounds->phiMin(), annulusBounds->phiMax()}}; + } +} + +/// Create the Material Matrix +Acts::MaterialSlabMatrix Acts::FaserActsJsonGeometryConverter::jsonToMaterialMatrix( + const json& data) { + Acts::MaterialSlabMatrix mpMatrix; + // the input data must be array[array[object]] + for (auto& outer : data) { + Acts::MaterialSlabVector mpVector; + for (auto& inner : outer) { + mpVector.emplace_back(decodeMaterialSlab(inner)); + } + mpMatrix.push_back(std::move(mpVector)); + } + return mpMatrix; +} + +/// Create the BinUtility for this +Acts::BinUtility Acts::FaserActsJsonGeometryConverter::jsonToBinUtility( + const json& bin) { + if (bin.size() >= 3) { + // finding the iterator position to determine the binning value + auto bit = std::find(Acts::binningValueNames.begin(), + Acts::binningValueNames.end(), bin[0]); + size_t indx = std::distance(Acts::binningValueNames.begin(), bit); + Acts::BinningValue bval = Acts::BinningValue(indx); + Acts::BinningOption bopt = bin[1] == "open" ? Acts::open : Acts::closed; + unsigned int bins = bin[2]; + float min = 0; + float max = 0; + if (bin.size() >= 4 && bin[3].size() == 2) { + min = bin[3][0]; + max = bin[3][1]; + } + return Acts::BinUtility(bins, min, max, bopt, bval); + } + return Acts::BinUtility(); +} + +/// Create the local to global transform +Acts::Transform3D Acts::FaserActsJsonGeometryConverter::jsonToTransform( + const json& transfo) { + Transform3D transform; + int i = 0; + int j = 0; + for (auto& element : transfo) { + transform(j, i) = element; + j++; + if (j == 4) { + i++; + j = 0; + } + } + return transform; +} + +Acts::BinUtility Acts::FaserActsJsonGeometryConverter::DefaultBin( + const Acts::Surface& surface) { + Acts::BinUtility bUtility; + + const Acts::SurfaceBounds& surfaceBounds = surface.bounds(); + const Acts::RadialBounds* radialBounds = + dynamic_cast<const Acts::RadialBounds*>(&surfaceBounds); + const Acts::CylinderBounds* cylinderBounds = + dynamic_cast<const Acts::CylinderBounds*>(&surfaceBounds); + const Acts::AnnulusBounds* annulusBounds = + dynamic_cast<const Acts::AnnulusBounds*>(&surfaceBounds); + const Acts::RectangleBounds* rectangleBounds = + dynamic_cast<const Acts::RectangleBounds*>(&surfaceBounds); + + if (radialBounds != nullptr) { + bUtility += BinUtility( + 1, + radialBounds->get(RadialBounds::eAveragePhi) - + radialBounds->get(RadialBounds::eHalfPhiSector), + radialBounds->get(RadialBounds::eAveragePhi) + + radialBounds->get(RadialBounds::eHalfPhiSector), + (radialBounds->get(RadialBounds::eHalfPhiSector) - M_PI) < s_epsilon + ? Acts::closed + : Acts::open, + Acts::binPhi); + bUtility += BinUtility(1, radialBounds->rMin(), radialBounds->rMax(), + Acts::open, Acts::binR); + return bUtility; + } + if (cylinderBounds != nullptr) { + bUtility += BinUtility( + 1, + cylinderBounds->get(CylinderBounds::eAveragePhi) - + cylinderBounds->get(CylinderBounds::eHalfPhiSector), + cylinderBounds->get(CylinderBounds::eAveragePhi) + + cylinderBounds->get(CylinderBounds::eHalfPhiSector), + (cylinderBounds->get(CylinderBounds::eHalfPhiSector) - M_PI) < s_epsilon + ? Acts::closed + : Acts::open, + Acts::binPhi); + bUtility += + BinUtility(1, -1 * cylinderBounds->get(CylinderBounds::eHalfLengthZ), + cylinderBounds->get(CylinderBounds::eHalfLengthZ), + Acts::open, Acts::binZ); + return bUtility; + } + if (annulusBounds != nullptr) { + bUtility += BinUtility(1, annulusBounds->get(AnnulusBounds::eMinPhiRel), + annulusBounds->get(AnnulusBounds::eMaxPhiRel), + Acts::open, Acts::binPhi); + bUtility += BinUtility(1, annulusBounds->rMin(), annulusBounds->rMax(), + Acts::open, Acts::binR); + return bUtility; + } + if (rectangleBounds != nullptr) { + bUtility += BinUtility(1, rectangleBounds->get(RectangleBounds::eMinX), + rectangleBounds->get(RectangleBounds::eMaxX), + Acts::open, Acts::binX); + bUtility += BinUtility(1, rectangleBounds->get(RectangleBounds::eMinY), + rectangleBounds->get(RectangleBounds::eMaxY), + Acts::open, Acts::binY); + return bUtility; + } + ACTS_INFO( + "No corresponding bound found for the surface : " << surface.name()); + return bUtility; +} + +Acts::BinUtility Acts::FaserActsJsonGeometryConverter::DefaultBin( + const Acts::TrackingVolume& volume) { + Acts::BinUtility bUtility; + + auto cyBounds = + dynamic_cast<const CylinderVolumeBounds*>(&(volume.volumeBounds())); + auto cutcylBounds = + dynamic_cast<const CutoutCylinderVolumeBounds*>(&(volume.volumeBounds())); + auto cuBounds = + dynamic_cast<const CuboidVolumeBounds*>(&(volume.volumeBounds())); + + if (cyBounds != nullptr) { + bUtility += BinUtility(1, cyBounds->get(CylinderVolumeBounds::eMinR), + cyBounds->get(CylinderVolumeBounds::eMaxR), + Acts::open, Acts::binR); + bUtility += BinUtility( + 1, -cyBounds->get(CylinderVolumeBounds::eHalfPhiSector), + cyBounds->get(CylinderVolumeBounds::eHalfPhiSector), + (cyBounds->get(CylinderVolumeBounds::eHalfPhiSector) - M_PI) < s_epsilon + ? Acts::closed + : Acts::open, + Acts::binPhi); + bUtility += + BinUtility(1, -cyBounds->get(CylinderVolumeBounds::eHalfLengthZ), + cyBounds->get(CylinderVolumeBounds::eHalfLengthZ), + Acts::open, Acts::binZ); + return bUtility; + } + if (cutcylBounds != nullptr) { + bUtility += + BinUtility(1, cutcylBounds->get(CutoutCylinderVolumeBounds::eMinR), + cutcylBounds->get(CutoutCylinderVolumeBounds::eMaxR), + Acts::open, Acts::binR); + bUtility += BinUtility(1, -M_PI, M_PI, Acts::closed, Acts::binPhi); + bUtility += BinUtility( + 1, -cutcylBounds->get(CutoutCylinderVolumeBounds::eHalfLengthZ), + cutcylBounds->get(CutoutCylinderVolumeBounds::eHalfLengthZ), Acts::open, + Acts::binZ); + return bUtility; + } else if (cuBounds != nullptr) { + bUtility += BinUtility(1, -cuBounds->get(CuboidVolumeBounds::eHalfLengthX), + cuBounds->get(CuboidVolumeBounds::eHalfLengthX), + Acts::open, Acts::binX); + bUtility += BinUtility(1, -cuBounds->get(CuboidVolumeBounds::eHalfLengthY), + cuBounds->get(CuboidVolumeBounds::eHalfLengthY), + Acts::open, Acts::binY); + bUtility += BinUtility(1, -cuBounds->get(CuboidVolumeBounds::eHalfLengthZ), + cuBounds->get(CuboidVolumeBounds::eHalfLengthZ), + Acts::open, Acts::binZ); + return bUtility; + } + ACTS_INFO( + "No corresponding bound found for the volume : " << volume.volumeName()); + return bUtility; +} \ No newline at end of file diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsMaterialJsonWriterTool.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsMaterialJsonWriterTool.cxx new file mode 100644 index 00000000..fe033f8e --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsMaterialJsonWriterTool.cxx @@ -0,0 +1,62 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#include "FaserActsGeometry/FaserActsMaterialJsonWriterTool.h" + +#include "ActsInterop/Logger.h" + +#include <fstream> +#include <ios> +#include <iostream> +#include <stdexcept> + +// FaserActsMaterialJsonWriterTool::FaserActsMaterialJsonWriterTool(const std::string& type, const std::string& name, const IInterface* parent) : +// base_class(type, name, parent) +// { +// } +FaserActsMaterialJsonWriterTool::FaserActsMaterialJsonWriterTool(const std::string &type, const std::string &name, + const IInterface *parent) + : base_class(type, name, parent) +{ +} + +StatusCode +FaserActsMaterialJsonWriterTool::initialize() +{ + ATH_MSG_INFO("Starting Material writer"); + + m_cfg.name = "FaserActsJsonGeometryConverter"; + m_cfg.logger = makeActsAthenaLogger(this, "FaserActsJsonGeometryConverter"); + m_cfg.processSensitives = m_processSensitives; + m_cfg.processApproaches = m_processApproaches; + m_cfg.processRepresenting = m_processRepresenting; + m_cfg.processBoundaries = m_processBoundaries; + m_cfg.processVolumes = m_processVolumes; + m_cfg.processDenseVolumes = m_processDenseVolumes; + m_cfg.processnonmaterial = m_processnonmaterial; + + return StatusCode::SUCCESS; +} + +void +FaserActsMaterialJsonWriterTool::write(const Acts::FaserActsJsonGeometryConverter::DetectorMaterialMaps& detMaterial) const +{ + // Evoke the converter + Acts::FaserActsJsonGeometryConverter jmConverter(m_cfg); + auto jout = jmConverter.materialMapsToJson(detMaterial); + // And write the file + std::ofstream ofj(m_filePath); + ofj << std::setw(4) << jout << std::endl; +} + +void +FaserActsMaterialJsonWriterTool::write(const Acts::TrackingGeometry& tGeometry) const +{ + // Evoke the converter + Acts::FaserActsJsonGeometryConverter jmConverter(m_cfg); + auto jout = jmConverter.trackingGeometryToJson(tGeometry); + // And write the file + std::ofstream ofj(m_filePath); + ofj << std::setw(4) << jout << std::endl; +} diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsMaterialMapping.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsMaterialMapping.cxx new file mode 100644 index 00000000..70a2ccec --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsMaterialMapping.cxx @@ -0,0 +1,135 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#include "FaserActsGeometry/FaserActsMaterialMapping.h" + +// ATHENA +#include "Acts/Surfaces/PerigeeSurface.hpp" +#include "Acts/Utilities/Logger.hpp" +#include "ActsInterop/Logger.h" +#include "GaudiKernel/EventContext.h" +#include "GaudiKernel/ISvcLocator.h" + +// ACTS +#include "Acts/Propagator/detail/SteppingLogger.hpp" +#include "Acts/Utilities/Helpers.hpp" +#include "Acts/Utilities/Units.hpp" + +// PACKAGE +#include "FaserActsGeometry/FaserActsGeometryContext.h" +#include "FaserActsGeometry/IFaserActsPropStepRootWriterSvc.h" + +// STL +#include <fstream> +#include <string> + +//TEST +#include "Acts/EventData/NeutralTrackParameters.hpp" +#include "Acts/Propagator/ActionList.hpp" +#include "Acts/Propagator/Navigator.hpp" +#include "Acts/Propagator/Propagator.hpp" +#include "Acts/Propagator/StandardAborters.hpp" +#include "Acts/Propagator/StraightLineStepper.hpp" + +FaserActsMaterialMapping::FaserActsMaterialMapping(const std::string &name, + ISvcLocator *pSvcLocator) + : AthReentrantAlgorithm(name, pSvcLocator), + m_materialTrackWriterSvc("ActsMaterialTrackWriterSvc", name), + m_inputMaterialStepCollection("MaterialStepRecords"), + m_mappingState(m_gctx,m_mctx), + m_mappingStateVol(m_gctx,m_mctx) +{} + +StatusCode FaserActsMaterialMapping::initialize() { + ATH_MSG_DEBUG(name() << "::" << __FUNCTION__); + + if(!m_mapSurfaces && !m_mapVolumes){ + ATH_MSG_ERROR("No element to map onto defined."); + return StatusCode::FAILURE; + } + + ATH_CHECK(m_materialStepConverterTool.retrieve() ); + ATH_CHECK(m_materialTrackWriterSvc.retrieve() ); + if(m_mapSurfaces){ + ATH_CHECK(m_surfaceMappingTool.retrieve() ); + m_mappingState = m_surfaceMappingTool->mappingState(); + } + if(m_mapVolumes){ + ATH_CHECK(m_volumeMappingTool.retrieve() ); + m_mappingStateVol = m_volumeMappingTool->mappingState(); + } + ATH_CHECK(m_materialJsonWriterTool.retrieve() ); + ATH_CHECK( m_inputMaterialStepCollection.initialize() ); + return StatusCode::SUCCESS; +} + +StatusCode FaserActsMaterialMapping::execute(const EventContext &ctx) const { + ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__); + + Acts::RecordedMaterialTrack mTrack; + SG::ReadHandle<Trk::MaterialStepCollection> materialStepCollection(m_inputMaterialStepCollection, ctx); + mTrack = m_materialStepConverterTool->convertToMaterialTrack(*materialStepCollection); + + if(m_mapSurfaces){ + auto mappingState + = const_cast<Acts::SurfaceMaterialMapper::State *>(&m_mappingState); + m_surfaceMappingTool->mapper()->mapMaterialTrack(*mappingState, mTrack); + } + if(m_mapVolumes){ + auto mappingStateVol + = const_cast<Acts::VolumeMaterialMapper::State *>(&m_mappingStateVol); + m_volumeMappingTool->mapper()->mapMaterialTrack(*mappingStateVol, mTrack); + } + m_materialTrackWriterSvc->write(mTrack); + ATH_MSG_VERBOSE(name() << " execute done"); + return StatusCode::SUCCESS; +} + +StatusCode FaserActsMaterialMapping::finalize() { + + Acts::DetectorMaterialMaps detectorMaterial; + + // Finalize all the maps using the cached state + if(m_mapSurfaces && m_mapVolumes){ + m_surfaceMappingTool->mapper()->finalizeMaps(m_mappingState); + m_volumeMappingTool->mapper()->finalizeMaps(m_mappingStateVol); + // Loop over the state, and collect the maps for surfaces + for (auto& [key, value] : m_mappingState.surfaceMaterial) { + detectorMaterial.first.insert({key, std::move(value)}); + } + // Loop over the state, and collect the maps for volumes + for (auto& [key, value] : m_mappingStateVol.volumeMaterial) { + detectorMaterial.second.insert({key, std::move(value)}); + } + } + else{ + if(m_mapSurfaces){ + m_surfaceMappingTool->mapper()->finalizeMaps(m_mappingState); + // Loop over the state, and collect the maps for surfaces + for (auto& [key, value] : m_mappingState.surfaceMaterial) { + detectorMaterial.first.insert({key, std::move(value)}); + } + // Loop over the state, and collect the maps for volumes + for (auto& [key, value] : m_mappingState.volumeMaterial) { + detectorMaterial.second.insert({key, std::move(value)}); + } + } + if(m_mapVolumes){ + m_volumeMappingTool->mapper()->finalizeMaps(m_mappingStateVol); + // Loop over the state, and collect the maps for surfaces + for (auto& [key, value] : m_mappingStateVol.surfaceMaterial) { + detectorMaterial.first.insert({key, std::move(value)}); + } + // Loop over the state, and collect the maps for volumes + for (auto& [key, value] : m_mappingStateVol.volumeMaterial) { + detectorMaterial.second.insert({key, std::move(value)}); + } + } + } + + m_materialJsonWriterTool->write(detectorMaterial); + + return StatusCode::SUCCESS; + +} \ No newline at end of file diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsSurfaceMappingTool.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsSurfaceMappingTool.cxx new file mode 100644 index 00000000..e2ff5c10 --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsSurfaceMappingTool.cxx @@ -0,0 +1,67 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#include "FaserActsGeometry/FaserActsSurfaceMappingTool.h" + +// ATHENA +#include "GaudiKernel/IInterface.h" +// PACKAGE +#include "ActsInterop/Logger.h" +#include "FaserActsGeometry/FaserActsGeometryContext.h" +#include "FaserActsGeometry/FaserActsTrackingGeometryTool.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" + +// ACTS +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Propagator/Navigator.hpp" +#include "Acts/Propagator/Propagator.hpp" +#include "Acts/Propagator/StraightLineStepper.hpp" + +// STL +#include <iostream> +#include <memory> + + +FaserActsSurfaceMappingTool::FaserActsSurfaceMappingTool(const std::string& type, const std::string& name, + const IInterface* parent) + : base_class(type, name, parent) +{ +} + +StatusCode +FaserActsSurfaceMappingTool::initialize() +{ + ATH_MSG_INFO("Initializing ACTS Surface Mapper"); + + ATH_CHECK( m_trackingGeometryTool.retrieve() ); + + m_trackingGeometry = m_trackingGeometryTool->trackingGeometry(); + + Acts::Navigator navigator(m_trackingGeometry); + // Make stepper and propagator + SlStepper stepper; + StraightLinePropagator propagator = StraightLinePropagator(std::move(stepper), std::move(navigator)); + + /// The material mapper + Acts::SurfaceMaterialMapper::Config smmConfig; + smmConfig.mapperDebugOutput = true; + m_mapper = std::make_shared<Acts::SurfaceMaterialMapper>( + smmConfig, + std::move(propagator), + makeActsAthenaLogger(this, "SurfaceMaterialMapper")); + + m_geoContext = m_trackingGeometryTool->getNominalGeometryContext().any(); + + ATH_MSG_INFO("ACTS Surface Mapper successfully initialized"); + return StatusCode::SUCCESS; +} + +Acts::SurfaceMaterialMapper::State +FaserActsSurfaceMappingTool::mappingState() const +{ + auto mappingState = m_mapper->createState( + m_geoContext, m_magFieldContext, *m_trackingGeometry); + + return mappingState; +} \ No newline at end of file diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsVolumeMappingTool.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsVolumeMappingTool.cxx new file mode 100644 index 00000000..234a7f2b --- /dev/null +++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsVolumeMappingTool.cxx @@ -0,0 +1,69 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#include "FaserActsGeometry/FaserActsVolumeMappingTool.h" + +// ATHENA +#include "GaudiKernel/IInterface.h" + +// PACKAGE +#include "FaserActsGeometry/FaserActsGeometryContext.h" +#include "ActsInterop/Logger.h" +#include "FaserActsGeometry/FaserActsTrackingGeometryTool.h" +//#include "ActsGeometry/ActsGeometryContext.h" +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" + +// ACTS +#include "Acts/Propagator/Navigator.hpp" +#include "Acts/Propagator/Propagator.hpp" +#include "Acts/Propagator/StraightLineStepper.hpp" +#include "Acts/Geometry/GeometryContext.hpp" + +// STL +#include <iostream> +#include <memory> + + +FaserActsVolumeMappingTool::FaserActsVolumeMappingTool(const std::string& type, const std::string& name, + const IInterface* parent) + : base_class(type, name, parent) +{ +} + +StatusCode +FaserActsVolumeMappingTool::initialize() +{ + ATH_MSG_INFO("Initializing ACTS Volume Mapper"); + + ATH_CHECK( m_trackingGeometryTool.retrieve() ); + + m_trackingGeometry = m_trackingGeometryTool->trackingGeometry(); + + Acts::Navigator navigator(m_trackingGeometry); + // Make stepper and propagator + SlStepper stepper; + StraightLinePropagator propagator = StraightLinePropagator(std::move(stepper), std::move(navigator)); + + /// The material mapper + Acts::VolumeMaterialMapper::Config smmConfig; + smmConfig.mappingStep = 10; + m_mapper = std::make_shared<Acts::VolumeMaterialMapper>( + smmConfig, + std::move(propagator), + makeActsAthenaLogger(this, "VolumeMaterialMapper")); + + m_geoContext = m_trackingGeometryTool->getNominalGeometryContext().any(); + + ATH_MSG_INFO("ACTS Surface Mapper successfully initialized"); + return StatusCode::SUCCESS; +} + +Acts::VolumeMaterialMapper::State +FaserActsVolumeMappingTool::mappingState() const +{ + auto mappingState = m_mapper->createState( + m_geoContext, m_magFieldContext, *m_trackingGeometry); + + return mappingState; +} diff --git a/Tracking/Acts/FaserActsGeometry/src/components/FaserActsGeometry_entries.cxx b/Tracking/Acts/FaserActsGeometry/src/components/FaserActsGeometry_entries.cxx index 9ad80a9d..9be7649a 100755 --- a/Tracking/Acts/FaserActsGeometry/src/components/FaserActsGeometry_entries.cxx +++ b/Tracking/Acts/FaserActsGeometry/src/components/FaserActsGeometry_entries.cxx @@ -16,7 +16,10 @@ //#include "FaserActsGeometry/FaserActsMaterialTrackWriterSvc.h" //#include "FaserActsGeometry/GeomShiftCondAlg.h" //#include "FaserActsGeometry/FaserActsWriteTrackingGeometryTransforms.h" - +#include "FaserActsGeometry/FaserActsVolumeMappingTool.h" +#include "FaserActsGeometry/FaserActsMaterialJsonWriterTool.h" +#include "FaserActsGeometry/FaserActsMaterialMapping.h" +#include "FaserActsGeometry/FaserActsSurfaceMappingTool.h" DECLARE_COMPONENT( FaserActsTrackingGeometrySvc ) DECLARE_COMPONENT( FaserActsTrackingGeometryTool ) @@ -32,3 +35,7 @@ DECLARE_COMPONENT( FaserActsAlignmentCondAlg ) //DECLARE_COMPONENT( FaserActsMaterialTrackWriterSvc ) //DECLARE_COMPONENT( FaserActsWriteTrackingGeometryTransforms ) //DECLARE_COMPONENT( FaserGeomShiftCondAlg ) +DECLARE_COMPONENT( FaserActsVolumeMappingTool ) +DECLARE_COMPONENT( FaserActsMaterialJsonWriterTool ) +DECLARE_COMPONENT( FaserActsMaterialMapping ) +DECLARE_COMPONENT( FaserActsSurfaceMappingTool ) diff --git a/Tracking/Acts/FaserActsGeometryInterfaces/CMakeLists.txt b/Tracking/Acts/FaserActsGeometryInterfaces/CMakeLists.txt index 633d8584..7529f472 100644 --- a/Tracking/Acts/FaserActsGeometryInterfaces/CMakeLists.txt +++ b/Tracking/Acts/FaserActsGeometryInterfaces/CMakeLists.txt @@ -5,7 +5,7 @@ atlas_subdir( FaserActsGeometryInterfaces ) # External dependencies: find_package( Eigen ) find_package( Acts COMPONENTS Core ) - +find_package( nlohmann_json ) # Component(s) in the package: atlas_add_library( FaserActsGeometryInterfacesLib @@ -13,7 +13,7 @@ atlas_add_library( FaserActsGeometryInterfacesLib INTERFACE PUBLIC_HEADERS FaserActsGeometryInterfaces INCLUDE_DIRS ${EIGEN_INCLUDE_DIRS} - LINK_LIBRARIES ${EIGEN_LIBRARIES} + LINK_LIBRARIES ${EIGEN_LIBRARIES} nlohmann_json::nlohmann_json AthenaKernel ActsInteropLib ActsCore) diff --git a/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsMaterialJsonWriterTool.h b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsMaterialJsonWriterTool.h new file mode 100644 index 00000000..7fe13c59 --- /dev/null +++ b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsMaterialJsonWriterTool.h @@ -0,0 +1,36 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ACTSGEOMETRY_IFASERACTSMATERIALJSONWRITERTOOL_H +#define ACTSGEOMETRY_IFASERACTSMATERIALJSONWRITERTOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/IAlgTool.h" + +#include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Plugins/Json/JsonGeometryConverter.hpp" +#include "FaserActsGeometry/FaserActsJsonGeometryConverter.h" + +namespace Acts { + class TrackingGeometry; +} + +class IFaserActsMaterialJsonWriterTool : virtual public IAlgTool { +public: + + DeclareInterfaceID(IFaserActsMaterialJsonWriterTool, 1, 0); + + virtual + void + write(const Acts::FaserActsJsonGeometryConverter::DetectorMaterialMaps& detMaterial) const = 0; + + virtual + void + write(const Acts::TrackingGeometry& tGeometry) const = 0; + +}; + + +#endif diff --git a/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsSurfaceMappingTool.h b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsSurfaceMappingTool.h new file mode 100644 index 00000000..29563126 --- /dev/null +++ b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsSurfaceMappingTool.h @@ -0,0 +1,37 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef FASERACTSGEOMETRYINTERFACES_IFASERACTSSURFACEMAPPINGTOOL_H +#define FASERACTSGEOMETRYINTERFACES_IFASERACTSSURFACEMAPPINGTOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/IAlgTool.h" +#include "GaudiKernel/EventContext.h" + +#include "Acts/Material/SurfaceMaterialMapper.hpp" + +class IFaserActsTrackingGeometryTool; + +class IFaserActsSurfaceMappingTool : virtual public IAlgTool { + public: + + DeclareInterfaceID(IFaserActsSurfaceMappingTool, 1, 0); + + + virtual + std::shared_ptr<Acts::SurfaceMaterialMapper> + mapper() const = 0; + + virtual + Acts::SurfaceMaterialMapper::State + mappingState() const = 0; + + virtual + const IFaserActsTrackingGeometryTool* + trackingGeometryTool() const = 0; + +}; + +#endif diff --git a/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h index e13ff445..82327941 100644 --- a/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h +++ b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h @@ -2,8 +2,8 @@ Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ -#ifndef FASERACTSGEOMETRYINTERFACES_IACTSTRACKINGGEOMETRYTOOL_H -#define FASERACTSGEOMETRYINTERFACES_IACTSTRACKINGGEOMETRYTOOL_H +#ifndef ACTSGEOMETRYINTERFACES_IACTSTRACKINGGEOMETRYTOOL_H +#define ACTSGEOMETRYINTERFACES_IACTSTRACKINGGEOMETRYTOOL_H #include "AthenaBaseComps/AthAlgTool.h" #include "GaudiKernel/IInterface.h" diff --git a/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsVolumeMappingTool.h b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsVolumeMappingTool.h new file mode 100644 index 00000000..b87e4638 --- /dev/null +++ b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsVolumeMappingTool.h @@ -0,0 +1,37 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef ACTSGEOMETRYINTERFACES_IACTSVOLUMEMAPPINGTOOL_H +#define ACTSGEOMETRYINTERFACES_IACTSVOLUMEMAPPINGTOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/IAlgTool.h" +#include "GaudiKernel/EventContext.h" + +#include "Acts/Material/VolumeMaterialMapper.hpp" + +class IFaserActsTrackingGeometryTool; + +class IFaserActsVolumeMappingTool : virtual public IAlgTool { + public: + + DeclareInterfaceID(IFaserActsVolumeMappingTool, 1, 0); + + + virtual + std::shared_ptr<Acts::VolumeMaterialMapper> + mapper() const = 0; + + virtual + Acts::VolumeMaterialMapper::State + mappingState() const = 0; + + virtual + const IFaserActsTrackingGeometryTool* + trackingGeometryTool() const = 0; + +}; + +#endif -- GitLab