From d56e69c57af381b2187bf50347c7e92c71a62254 Mon Sep 17 00:00:00 2001 From: Robert Johannes Langenberg <robert.langenberg@cern.ch> Date: Fri, 19 Jun 2020 14:41:25 +0000 Subject: [PATCH] Tracking geometry conditions alg --- .../CaloTrackingGeometryBuilderCond.h | 145 + ...nfiguredCaloTrackingGeometryBuilderCond.py | 48 + .../src/CaloTrackingGeometryBuilder.cxx | 3 +- .../src/CaloTrackingGeometryBuilderCond.cxx | 1698 +++++++++++ .../CaloTrackingGeometry_entries.cxx | 3 + .../BeamPipeBuilderCond.h | 119 + .../RobustTrackingGeometryBuilderCond.h | 138 + .../SiLayerBuilderCond.h | 162 + .../StagedTrackingGeometryBuilderCond.h | 255 ++ .../TRT_LayerBuilderCond.h | 117 + ...figuredInDetTrackingGeometryBuilderCond.py | 201 ++ ...iguredStagedTrackingGeometryBuilderCond.py | 223 ++ .../src/BeamPipeBuilderCond.cxx | 170 ++ .../src/RobustTrackingGeometryBuilderCond.cxx | 771 +++++ .../src/SiLayerBuilderCond.cxx | 1178 ++++++++ .../src/StagedTrackingGeometryBuilderCond.cxx | 718 +++++ .../src/TRT_LayerBuilderCond.cxx | 729 +++++ .../InDetTrackingGeometry_entries.cxx | 12 + .../MuonTrackingGeometryBuilderCond.h | 190 ++ ...nfiguredMuonTrackingGeometryBuilderCond.py | 44 + .../ConfiguredMuonTrackingGeometryCond.py | 30 + .../src/MuonTrackingGeometryBuilderCond.cxx | 2655 +++++++++++++++++ .../MuonTrackingGeometry_entries.cxx | 2 + .../LayerMaterialProvider.h | 12 +- .../src/LayerMaterialProvider.cxx | 12 +- .../TrackingGeometryCondAlg/CMakeLists.txt | 40 + .../TrackingGeometryCondAlg.h | 45 + .../python/AtlasTrackingGeometryCondAlg.py | 180 ++ .../AtlasTrackingGeometryCondAlgConfig.py | 293 ++ .../src/TrackingGeometryCondAlg.cxx | 71 + .../TrackingGeometryCondAlg_entries.cxx | 3 + .../TrkConditions/TrkCondTest/CMakeLists.txt | 40 + .../TrkCondTest/TrackingGeometryCondAlgTest.h | 40 + .../share/TrackingGeometryTest_jobOptions.py | 105 + .../src/TrackingGeometryCondAlgTest.cxx | 47 + .../src/components/TrkCondTest_entries.cxx | 3 + .../IGeometryBuilderCond.h | 69 + .../IGeometryProcessor.h | 10 +- .../TrkDetDescrInterfaces/ILayerBuilderCond.h | 73 + .../ILayerProviderCond.h | 62 + .../GeometryAsciiDumper.h | 10 +- .../TrkDetDescrTestTools/GeometryJsonDumper.h | 12 +- .../GeometryTTreeDumper.h | 10 +- .../LayerMaterialInspector.h | 10 +- .../RecursiveGeometryProcessor.h | 16 +- .../TrackingVolumeDisplayer.h | 8 +- .../src/GeometryAsciiDumper.cxx | 8 +- .../src/GeometryJsonDumper.cxx | 8 +- .../src/GeometryTTreeDumper.cxx | 8 +- .../src/LayerMaterialInspector.cxx | 8 +- .../src/RecursiveGeometryProcessor.cxx | 16 +- .../src/TrackingVolumeDisplayer.cxx | 8 +- .../GenericGeometryBuilderCond.h | 83 + .../TrkDetDescrTools/GeometryBuilderCond.h | 107 + .../InputLayerMaterialProvider.h | 10 +- .../TrkDetDescrTools/LayerMaterialProvider.h | 16 +- .../TrkDetDescrTools/LayerProviderCond.h | 72 + .../src/GenericGeometryBuilderCond.cxx | 281 ++ .../src/GeometryBuilderCond.cxx | 451 +++ .../src/InputLayerMaterialProvider.cxx | 10 +- .../src/LayerMaterialProvider.cxx | 36 +- .../src/LayerProviderCond.cxx | 114 + .../components/TrkDetDescrTools_entries.cxx | 7 + .../TrkGeometry/TrackingGeometry.h | 6 + 64 files changed, 11919 insertions(+), 112 deletions(-) create mode 100755 Calorimeter/CaloTrackingGeometry/CaloTrackingGeometry/CaloTrackingGeometryBuilderCond.h create mode 100644 Calorimeter/CaloTrackingGeometry/python/ConfiguredCaloTrackingGeometryBuilderCond.py create mode 100755 Calorimeter/CaloTrackingGeometry/src/CaloTrackingGeometryBuilderCond.cxx create mode 100755 InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/BeamPipeBuilderCond.h create mode 100755 InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/RobustTrackingGeometryBuilderCond.h create mode 100755 InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/SiLayerBuilderCond.h create mode 100755 InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/StagedTrackingGeometryBuilderCond.h create mode 100755 InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/TRT_LayerBuilderCond.h create mode 100644 InnerDetector/InDetDetDescr/InDetTrackingGeometry/python/ConfiguredInDetTrackingGeometryBuilderCond.py create mode 100644 InnerDetector/InDetDetDescr/InDetTrackingGeometry/python/ConfiguredStagedTrackingGeometryBuilderCond.py create mode 100755 InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/BeamPipeBuilderCond.cxx create mode 100755 InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/RobustTrackingGeometryBuilderCond.cxx create mode 100755 InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/SiLayerBuilderCond.cxx create mode 100755 InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/StagedTrackingGeometryBuilderCond.cxx create mode 100755 InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/TRT_LayerBuilderCond.cxx create mode 100644 MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/MuonTrackingGeometry/MuonTrackingGeometryBuilderCond.h create mode 100644 MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/python/ConfiguredMuonTrackingGeometryBuilderCond.py create mode 100644 MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/python/ConfiguredMuonTrackingGeometryCond.py create mode 100644 MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/src/MuonTrackingGeometryBuilderCond.cxx create mode 100644 Tracking/TrkConditions/TrackingGeometryCondAlg/CMakeLists.txt create mode 100644 Tracking/TrkConditions/TrackingGeometryCondAlg/TrackingGeometryCondAlg/TrackingGeometryCondAlg.h create mode 100644 Tracking/TrkConditions/TrackingGeometryCondAlg/python/AtlasTrackingGeometryCondAlg.py create mode 100644 Tracking/TrkConditions/TrackingGeometryCondAlg/python/AtlasTrackingGeometryCondAlgConfig.py create mode 100644 Tracking/TrkConditions/TrackingGeometryCondAlg/src/TrackingGeometryCondAlg.cxx create mode 100644 Tracking/TrkConditions/TrackingGeometryCondAlg/src/components/TrackingGeometryCondAlg_entries.cxx create mode 100644 Tracking/TrkConditions/TrkCondTest/CMakeLists.txt create mode 100644 Tracking/TrkConditions/TrkCondTest/TrkCondTest/TrackingGeometryCondAlgTest.h create mode 100644 Tracking/TrkConditions/TrkCondTest/share/TrackingGeometryTest_jobOptions.py create mode 100644 Tracking/TrkConditions/TrkCondTest/src/TrackingGeometryCondAlgTest.cxx create mode 100644 Tracking/TrkConditions/TrkCondTest/src/components/TrkCondTest_entries.cxx create mode 100755 Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/IGeometryBuilderCond.h create mode 100755 Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/ILayerBuilderCond.h create mode 100644 Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/ILayerProviderCond.h create mode 100644 Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/GenericGeometryBuilderCond.h create mode 100755 Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/GeometryBuilderCond.h create mode 100644 Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/LayerProviderCond.h create mode 100644 Tracking/TrkDetDescr/TrkDetDescrTools/src/GenericGeometryBuilderCond.cxx create mode 100755 Tracking/TrkDetDescr/TrkDetDescrTools/src/GeometryBuilderCond.cxx create mode 100644 Tracking/TrkDetDescr/TrkDetDescrTools/src/LayerProviderCond.cxx diff --git a/Calorimeter/CaloTrackingGeometry/CaloTrackingGeometry/CaloTrackingGeometryBuilderCond.h b/Calorimeter/CaloTrackingGeometry/CaloTrackingGeometry/CaloTrackingGeometryBuilderCond.h new file mode 100755 index 00000000000..f13ae7ed2fb --- /dev/null +++ b/Calorimeter/CaloTrackingGeometry/CaloTrackingGeometry/CaloTrackingGeometryBuilderCond.h @@ -0,0 +1,145 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// CaloTrackingGeometryBuilderCond.hm (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef CALORIMETER_CALOTRACKINGGEOMETRYBUILDERCOND_H +#define CALORIMETER_CALOTRACKINGGEOMETRYBUILDERCOND_H + +#include "CaloIdentifier/CaloCell_ID.h" +// Gaudi +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/ToolHandle.h" +#include "GaudiKernel/ServiceHandle.h" +// Trk +#include "TrkDetDescrInterfaces/IGeometryBuilderCond.h" +#include "TrkDetDescrUtils/GeometrySignature.h" +#include "TrkDetDescrUtils/LayerIndexSampleMap.h" +// EnvelopeDefinitionService +#include "SubDetectorEnvelopes/IEnvelopeDefSvc.h" + +// STL +#include <vector> + +namespace Trk { + class Material; + class Layer; + class MagneticFieldProperties; + class TrackingGeometry; + class ITrackingVolumeBuilder; + class ITrackingVolumeCreator; + class ITrackingVolumeHelper; + class ITrackingVolumeArrayCreator; + class IMagneticFieldTool; +} + +class IEnvelopeDefSvc; +class ICaloSurfaceHelper; + +namespace Calo { + + /** @class CaloTrackingGeometryBuilderCond + + Retrieves the volume builders from Tile and LAr + and combines the given volumes to a calorimeter tracking + geometry. + + It also wraps an inner volume if provided though + the mehtod interface. + + @author Andreas.Salzburger@cern.ch + */ + class CaloTrackingGeometryBuilderCond : public AthAlgTool, + virtual public Trk::IGeometryBuilderCond { + + + public: + /** Constructor */ + CaloTrackingGeometryBuilderCond(const std::string&,const std::string&,const IInterface*); + + /** Destructor */ + virtual ~CaloTrackingGeometryBuilderCond(); + + /** AlgTool initailize method.*/ + StatusCode initialize(); + + /** AlgTool finalize method */ + StatusCode finalize(); + + /** TrackingGeometry Interface methode */ + std::pair<EventIDRange, const Trk::TrackingGeometry*> trackingGeometry(const EventContext& ctx, std::pair<EventIDRange, const Trk::TrackingVolume*> tVolPair) const; + + /** The unique signature */ + Trk::GeometrySignature geometrySignature() const { return Trk::Calo; } + + private: + ToolHandle<Trk::ITrackingVolumeArrayCreator> m_trackingVolumeArrayCreator; //!< Helper Tool to create TrackingVolume Arrays + + ToolHandle<Trk::ITrackingVolumeHelper> m_trackingVolumeHelper; //!< Helper Tool to create TrackingVolumes + + ToolHandle<Trk::ITrackingVolumeCreator> m_trackingVolumeCreator; //!< Second helper for volume creation + + ToolHandle<Trk::ITrackingVolumeBuilder> m_lArVolumeBuilder; //!< Volume Builder for the Liquid Argon Calorimeter + + ToolHandle<Trk::ITrackingVolumeBuilder> m_tileVolumeBuilder; //!< Volume Builder for the Tile Calorimeter + + Trk::Material* m_caloMaterial; //!< Material properties + + double m_caloEnvelope; //!< Envelope cover for Gap Layers + //enclosing endcap/cylindervolume + ServiceHandle<IEnvelopeDefSvc> m_enclosingEnvelopeSvc; + + mutable double m_caloDefaultRadius; //!< the radius if not built from GeoModel + mutable double m_caloDefaultHalflengthZ; //!< the halflength in z if not built from GeoModel + + bool m_indexStaticLayers; //!< forces robust indexing for layers + + bool m_recordLayerIndexCaloSampleMap; //!< for deposition methods + std::string m_layerIndexCaloSampleMapName; //!< name to record it + + bool m_buildMBTS; //!< MBTS like detectors + //int m_mbstSurfaceShape; //!< MBTS like detectors + mutable std::vector<double> m_mbtsRadii; //!< MBTS like detectors + std::vector<double> m_mbtsRadiusGap; //!< MBTS like detectors + std::vector<int> m_mbtsPhiSegments; //!< MBTS like detectors + std::vector<double> m_mbtsPhiGap; //!< MBTS like detectors + std::vector<double> m_mbtsPositionZ; //!< MBTS like detectors + std::vector<double> m_mbtsStaggeringZ; //!< MBTS like detectors + + std::string m_entryVolume; //!< name of the Calo entrance + std::string m_exitVolume; //!< name of the Calo container + + mutable RZPairVector m_bpCutouts; + + // MBTS layers + mutable std::vector<const Trk::Layer*>* m_mbtsNegLayers; + mutable std::vector<const Trk::Layer*>* m_mbtsPosLayers; + //ToolHandle<ICaloSurfaceHelper> m_caloSurfaceHelper; + + /** method to establish a link between the LayerIndex and the CaloCell_ID in an associative container */ + void registerInLayerIndexCaloSampleMap(Trk::LayerIndexSampleMap& licsMAp, + std::vector<CaloCell_ID::CaloSample> ccid, + const Trk::TrackingVolume& vol, + int side = 1 ) const; + + /** method to build enclosed beam pipe volumes */ + std::pair<const Trk::TrackingVolume*, const Trk::TrackingVolume*> createBeamPipeVolumes(float ,float, std::string, float&) const; + + /** cleanup of material */ + mutable std::map<const Trk::Material*, bool> m_materialGarbage; + void throwIntoGarbage(const Trk::Material* mat) const; + + }; + +} // end of namespace + + +inline void Calo::CaloTrackingGeometryBuilderCond::throwIntoGarbage(const Trk::Material* mat) const +{ if (mat) m_materialGarbage[mat] = true; } + +#endif // CALORIMETER_CALOTRACKINGGEOMETRYBUILDERCOND_H + + diff --git a/Calorimeter/CaloTrackingGeometry/python/ConfiguredCaloTrackingGeometryBuilderCond.py b/Calorimeter/CaloTrackingGeometry/python/ConfiguredCaloTrackingGeometryBuilderCond.py new file mode 100644 index 00000000000..ccc3416c7cb --- /dev/null +++ b/Calorimeter/CaloTrackingGeometry/python/ConfiguredCaloTrackingGeometryBuilderCond.py @@ -0,0 +1,48 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + +###################################################### +# ConfiguredCaloTrackingGeometry module +# +# it inherits from CaloTrackingGeometryBuilder and performs +# standard configuration +# +###################################################### + +# import the Extrapolator configurable +from CaloTrackingGeometry.CaloTrackingGeometryConf import Calo__CaloTrackingGeometryBuilderCond + +# define the class +class ConfiguredCaloTrackingGeometryBuilderCond( Calo__CaloTrackingGeometryBuilderCond ): + # constructor + def __init__(self,name = 'CaloTrackingGeometryBuilderCond'): + + from TrkDetDescrSvc.TrkDetDescrJobProperties import TrkDetFlags + + from LArTrackingGeometry.ConfiguredLArVolumeBuilder import ConfiguredLArVolumeBuilder + + # import the ToolSvc + from AthenaCommon.AppMgr import ToolSvc + if 'ToolSvc' not in dir() : + ToolSvc = ToolSvc() + + ConfLArVolumeBuilder = ConfiguredLArVolumeBuilder() + ToolSvc += ConfLArVolumeBuilder + + from TileTrackingGeometry.ConfiguredTileVolumeBuilder import ConfiguredTileVolumeBuilder + + ConfTileVolumeBuilder = ConfiguredTileVolumeBuilder() + ToolSvc += ConfTileVolumeBuilder + + # The volume helper + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__TrackingVolumeHelper + CaloTrackingVolumeHelper = Trk__TrackingVolumeHelper(name='TrackingVolumeHelper') + ToolSvc += CaloTrackingVolumeHelper + + Calo__CaloTrackingGeometryBuilderCond.__init__(self,name,\ + LArVolumeBuilder = ConfLArVolumeBuilder,\ + TileVolumeBuilder = ConfTileVolumeBuilder,\ + TrackingVolumeHelper = CaloTrackingVolumeHelper,\ + GapLayerEnvelope = TrkDetFlags.CaloEnvelopeCover(),\ + EntryVolumeName = TrkDetFlags.CaloEntryVolumeName(),\ + ExitVolumeName = TrkDetFlags.CaloContainerName(), + MagneticFieldMode = TrkDetFlags.MagneticFieldMode()) diff --git a/Calorimeter/CaloTrackingGeometry/src/CaloTrackingGeometryBuilder.cxx b/Calorimeter/CaloTrackingGeometry/src/CaloTrackingGeometryBuilder.cxx index b5006daba4f..4fc2b86d5bd 100755 --- a/Calorimeter/CaloTrackingGeometry/src/CaloTrackingGeometryBuilder.cxx +++ b/Calorimeter/CaloTrackingGeometry/src/CaloTrackingGeometryBuilder.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -319,6 +319,7 @@ const Trk::TrackingGeometry* Calo::CaloTrackingGeometryBuilder::trackingGeometry RZPairVector& bpDefs = m_enclosingEnvelopeSvc->getBeamPipeRZValues(0); ATH_MSG_VERBOSE( "BeamPipe envelope definition retrieved:" ); + m_bpCutouts.clear(); for (unsigned int i=0; i<bpDefs.size(); i++) { ATH_MSG_VERBOSE( "Rz pair:"<< i<<":"<< bpDefs[i].first<<","<<bpDefs[i].second ); // beam pipe within calo : pick 10. < R < 200; envEnclosingVolumeHalfZ =< z <= msCutouts.back().second; diff --git a/Calorimeter/CaloTrackingGeometry/src/CaloTrackingGeometryBuilderCond.cxx b/Calorimeter/CaloTrackingGeometry/src/CaloTrackingGeometryBuilderCond.cxx new file mode 100755 index 00000000000..b736599facf --- /dev/null +++ b/Calorimeter/CaloTrackingGeometry/src/CaloTrackingGeometryBuilderCond.cxx @@ -0,0 +1,1698 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// CaloTrackingGeometryBuilderCond.cxx, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// +// Calo +#include "CaloTrackingGeometry/CaloTrackingGeometryBuilderCond.h" +#include "CaloTrackingGeometry/ICaloSurfaceHelper.h" +// Trk +#include "TrkDetDescrInterfaces/ITrackingVolumeBuilder.h" +#include "TrkDetDescrInterfaces/ITrackingVolumeCreator.h" +#include "TrkDetDescrInterfaces/ILayerArrayCreator.h" +#include "TrkDetDescrInterfaces/ITrackingVolumeArrayCreator.h" +#include "TrkDetDescrInterfaces/ITrackingVolumeHelper.h" +#include "TrkDetDescrInterfaces/IDynamicLayerCreator.h" +//#include "TrkDetDescrInterfaces/IMaterialEffectsOnTrackProvider.h" +#include "TrkDetDescrUtils/BinnedArray.h" +#include "TrkDetDescrUtils/BinnedArray1D1D.h" +#include "TrkDetDescrUtils/SharedObject.h" +#include "TrkDetDescrUtils/BinUtility.h" +#include "TrkDetDescrUtils/GeometryStatics.h" +#include "TrkGeometry/TrackingGeometry.h" +#include "TrkGeometry/TrackingVolume.h" +#include "TrkGeometry/GlueVolumesDescriptor.h" +#include "TrkGeometry/Material.h" +#include "TrkGeometry/BinnedMaterial.h" +#include "TrkGeometry/MaterialProperties.h" +#include "TrkGeometry/DiscLayer.h" +#include "TrkGeometry/HomogeneousLayerMaterial.h" +#include "TrkGeometry/AlignableTrackingVolume.h" +#include "TrkVolumes/VolumeBounds.h" +#include "TrkVolumes/CylinderVolumeBounds.h" +#include "TrkSurfaces/DiscBounds.h" +#include "TrkSurfaces/TrapezoidBounds.h" +#include "TrkSurfaces/DiscSurface.h" +#include "TrkSurfaces/PlaneSurface.h" +#include "GaudiKernel/SystemOfUnits.h" +#include <memory> +// CLHEP +//#include "CLHEP/Geometry/Transform3D.h" + +//using HepGeom::Transform3D; +//using HepGeom::Translate3D; +//using HepGeom::RotateZ3D; +//using HepGeom::Vector3D; +//using CLHEP::Hep3Vector; +//using CLHEP::HepRotation; +//using CLHEP::mm; +//using CLHEP::radian; + +// constructor +Calo::CaloTrackingGeometryBuilderCond::CaloTrackingGeometryBuilderCond(const std::string& t, const std::string& n, const IInterface* p) : + AthAlgTool(t,n,p), + m_trackingVolumeArrayCreator("Trk::TrackingVolumeArrayCreator/TrackingVolumeArrayCreator"), + m_trackingVolumeHelper("Trk::TrackingVolumeHelper/TrackingVolumeHelper"), + m_trackingVolumeCreator("Trk::CylinderVolumeCreator/TrackingVolumeCreator"), + m_lArVolumeBuilder("LAr::LArVolumeBuilder/LArVolumeBuilder"), + m_tileVolumeBuilder("Tile::TileVolumeBuilder/TileVolumeBuilder"), + m_caloMaterial(0), + m_caloEnvelope(25*Gaudi::Units::mm), + m_enclosingEnvelopeSvc("AtlasGeometry_EnvelopeDefSvc", n), + m_caloDefaultRadius(4250.), + m_caloDefaultHalflengthZ(6500.), + m_indexStaticLayers(true), + m_recordLayerIndexCaloSampleMap(false), + m_layerIndexCaloSampleMapName("LayerIndexCaloSampleMap"), + m_buildMBTS(true), + //m_mbstSurfaceShape(2), + m_entryVolume("Calo::Container::EntryVolume"), + m_exitVolume("Calo::Container"), + m_mbtsNegLayers(0), + m_mbtsPosLayers(0) + //m_caloSurfaceHelper("CaloSurfaceHelper/CaloSurfaceHelper") +{ + declareInterface<Trk::IGeometryBuilderCond>(this); + // declare the properties via Python + declareProperty("LArVolumeBuilder", m_lArVolumeBuilder); + declareProperty("TileVolumeBuilder", m_tileVolumeBuilder); + declareProperty("TrackingVolumeArrayCreator", m_trackingVolumeArrayCreator); + declareProperty("TrackingVolumeHelper", m_trackingVolumeHelper); + declareProperty("TrackingVolumeCreator", m_trackingVolumeCreator); + declareProperty("GapLayerEnvelope", m_caloEnvelope); + // envelope definition service + declareProperty("EnvelopeDefinitionSvc", m_enclosingEnvelopeSvc ); + // empty calorimeter to be built + declareProperty("CalorimeterRadius", m_caloDefaultRadius); + declareProperty("CalorimeterHalflengthZ", m_caloDefaultHalflengthZ); + // unique layer handling + declareProperty("IndexStaticLayers", m_indexStaticLayers); + // for energy deposition + declareProperty("RecordLayerIndexCaloSampleMap", m_recordLayerIndexCaloSampleMap); + declareProperty("LayerIndexCaloSampleMapName", m_layerIndexCaloSampleMapName); + // MBTS like detectors + declareProperty("BuildMBTS", m_buildMBTS); + //declareProperty("MBTS_SurfaceShape", m_mbstSurfaceShape); + //declareProperty("MBTS_Radii", m_mbtsRadii); + //declareProperty("MBTS_RadiusGap", m_mbtsRadiusGap); + //declareProperty("MBTS_PhiSegments", m_mbtsPhiSegments); + //declareProperty("MBTS_PhiGap", m_mbtsPhiGap); + //declareProperty("MBTS_PositionZ", m_mbtsPositionZ); + //declareProperty("MBTS_StaggeringZ", m_mbtsStaggeringZ); + // calo entry volume & exit volume + declareProperty("EntryVolumeName", m_entryVolume); + declareProperty("ExitVolumeName", m_exitVolume); + +} + +// destructor +Calo::CaloTrackingGeometryBuilderCond::~CaloTrackingGeometryBuilderCond() +{ + delete m_caloMaterial; +} + +// Athena standard methods +// initialize +StatusCode Calo::CaloTrackingGeometryBuilderCond::initialize() +{ + + // retrieve envelope definition service -------------------------------------------------- + if ( m_enclosingEnvelopeSvc.retrieve().isFailure() ){ + ATH_MSG_FATAL( "Could not retrieve EnvelopeDefinition service. Abort."); + return StatusCode::FAILURE; + } + + // Retrieve the tracking volume array creator ------------------------------------------------- + if (m_trackingVolumeArrayCreator.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool " << m_trackingVolumeArrayCreator ); + return StatusCode::FAILURE; + } else + ATH_MSG_INFO( "Retrieved tool " << m_trackingVolumeArrayCreator ); + + // Retrieve the tracking volume helper ------------------------------------------------- + if (m_trackingVolumeHelper.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool " << m_trackingVolumeHelper ); + return StatusCode::FAILURE; + } else + ATH_MSG_INFO( "Retrieved tool " << m_trackingVolumeHelper ); + + // Retrieve the second volume creator + if (m_buildMBTS && m_trackingVolumeCreator.retrieve().isFailure()){ + ATH_MSG_FATAL( "Failed to retrieve tool " << m_trackingVolumeCreator ); + return StatusCode::FAILURE; + } else + ATH_MSG_INFO( "Retrieved tool " << m_trackingVolumeCreator ); + + // Retrieve the volume builders + + // Retrieve the tracking volume array creator ------------------------------------------------- + if (m_lArVolumeBuilder.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool " << m_lArVolumeBuilder ); + return StatusCode::FAILURE; + } else + ATH_MSG_INFO( "Retrieved tool " << m_lArVolumeBuilder ); + + // Retrieve the tracking volume helper ------------------------------------------------- + if (m_tileVolumeBuilder.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool " << m_tileVolumeBuilder ); + return StatusCode::FAILURE; + } else + ATH_MSG_INFO( "Retrieved tool " << m_tileVolumeBuilder ); + + // Retrieve the calo surface helper (to load MBTS) ------------------------------------------------- +#if 0 + if (m_caloSurfaceHelper.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool " << m_caloSurfaceHelper ); + return StatusCode::FAILURE; + } else + ATH_MSG_INFO( "Retrieved tool " << m_caloSurfaceHelper ); +#endif + + // Dummy MaterialProerties + m_caloMaterial = new Trk::Material; + + ATH_MSG_INFO( "initialize() succesful" ); + + return StatusCode::SUCCESS; +} + +// finalize +StatusCode Calo::CaloTrackingGeometryBuilderCond::finalize() +{ + // empty the material garbage + std::map<const Trk::Material*, bool>::iterator garbageIter = m_materialGarbage.begin(); + std::map<const Trk::Material*, bool>::iterator garbageEnd = m_materialGarbage.end(); + + for ( ; garbageIter != garbageEnd; ++garbageIter ){ + delete (garbageIter->first); + } + + ATH_MSG_INFO( "finalize() successful" ); + return StatusCode::SUCCESS; +} + +std::pair<EventIDRange, const Trk::TrackingGeometry*> Calo::CaloTrackingGeometryBuilderCond::trackingGeometry(const EventContext&, std::pair<EventIDRange, const Trk::TrackingVolume*> tVolPair) const +{ + + ATH_MSG_VERBOSE( "Starting to build CaloTrackingGeometry ..." ); + + // the return TG + const Trk::TrackingGeometry* caloTrackingGeometry = 0; + const Trk::TrackingVolume* calorimeter = 0; + + // the key dimensions + RZPairVector keyDim; + + // the enclosed input volume (ID) + double enclosedInnerSectorHalflength = 0.; + double enclosedInnerSectorRadius = 0.; + + // dummy objects + const Trk::LayerArray* dummyLayers = 0; + const Trk::TrackingVolumeArray* dummyVolumes = 0; + + //TODO/FIXME: just passing on range, no Calo IOV range used + EventIDRange range; + const Trk::TrackingVolume* innerVol = nullptr; + if(tVolPair.second != nullptr){ + range = tVolPair.first; + innerVol = tVolPair.second; + } + if (innerVol) { + ATH_MSG_VERBOSE( "Got Inner Detector Volume: " << innerVol->volumeName() ); + innerVol->screenDump(msg(MSG::VERBOSE)); + + // retrieve dimensions + const Trk::CylinderVolumeBounds* innerDetectorBounds + = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(innerVol->volumeBounds())); + if (!innerDetectorBounds) std::abort(); + + enclosedInnerSectorHalflength = innerDetectorBounds->halflengthZ(); + enclosedInnerSectorRadius = innerDetectorBounds->outerRadius(); + + keyDim.push_back(RZPair(enclosedInnerSectorRadius, enclosedInnerSectorHalflength)); + } + // get the dimensions from the envelope service + RZPairVector& envelopeDefsIn = m_enclosingEnvelopeSvc->getCaloRZValues(0); + //RZPairVector& envelopeDefs = m_enclosingEnvelopeSvc->getCaloRZValues(0); + + // find the max,max pair + unsigned int ii=0; + for (unsigned int i=0; i<envelopeDefsIn.size(); i++) { + if (envelopeDefsIn[i].second>envelopeDefsIn[ii].second) ii=i; + else if (envelopeDefsIn[i].second==envelopeDefsIn[ii].second && + envelopeDefsIn[i].first>envelopeDefsIn[ii].first) ii=i; + } + + // find the sense of rotation + int irot=1; + unsigned int inext=ii+1; + if (inext==envelopeDefsIn.size()) inext=0; + if (envelopeDefsIn[inext].second!=envelopeDefsIn[ii].second) {irot=-1; inext = ii>0 ? ii-1:envelopeDefsIn.size()-1 ;} + + // fill starting with upper low edge, end with upper high edge + RZPairVector envelopeDefs; + if (irot>0) { + for (unsigned int i=inext; i<envelopeDefsIn.size(); i++) envelopeDefs.push_back(envelopeDefsIn[i]); + if (inext>0) for (unsigned int i=0; i<=inext-1; i++) envelopeDefs.push_back(envelopeDefsIn[i]); + } else { + int i=inext; while (i>=0) {envelopeDefs.push_back(envelopeDefsIn[i]); i=i-1;}; + inext = envelopeDefsIn.size()-1; while (inext>=ii) {envelopeDefs.push_back(envelopeDefsIn[inext]); inext=inext-1;}; + } + + + double envEnclosingVolumeHalfZ = m_caloDefaultHalflengthZ; + + ATH_MSG_VERBOSE( "Calo envelope definition retrieved:" ); + RZPairVector msCutouts; + for (unsigned int i=0; i<envelopeDefs.size(); i++) { + ATH_MSG_VERBOSE( "Rz pair:"<< i<<":"<< envelopeDefs[i].first<<","<<envelopeDefs[i].second ); + if (fabs(envelopeDefs[i].second) < envEnclosingVolumeHalfZ) envEnclosingVolumeHalfZ = fabs(envelopeDefs[i].second); + // ID dimensions : pick 1100 < R < 1200 + if ( envelopeDefs[i].first > 1100. && envelopeDefs[i].first < 1200. && envelopeDefs[i].second > 0. ) { + // check that radial size of ID envelope fits + if ( enclosedInnerSectorRadius != envelopeDefs[i].first ) ATH_MSG_INFO( "Enclosed ID volume radius does not match ID envelope, adjusting Calo." ); + envEnclosingVolumeHalfZ = envelopeDefs[i].second; + if (!innerVol) { + enclosedInnerSectorRadius = envelopeDefs[i].first; + enclosedInnerSectorHalflength = envelopeDefs[i].second; + } + } + // collect outer cutouts, process those with |z| < 6785.mm ( this cut should be synchronized with MS default size, + // MS builder would crash for a longer input volume ) + if ( envelopeDefs[i].second > 0. && envelopeDefs[i].second < 6785. && + ( envelopeDefs[i].first > 1200. || envelopeDefs[i].second > envEnclosingVolumeHalfZ ) ) { + if ( !msCutouts.size() ) msCutouts.push_back( envelopeDefs[i] ); + else { + RZPairVector::iterator envIter = msCutouts.begin(); + while (envIter!= msCutouts.end() && (*envIter).second < envelopeDefs[i].second ) envIter++; + while (envIter!= msCutouts.end() && (*envIter).second == envelopeDefs[i].second && (*envIter).first > envelopeDefs[i].first ) envIter++; + msCutouts.insert(envIter, envelopeDefs[i]); + } + } + // end outer (MS) cutouts + } + for (unsigned int i=0; i<msCutouts.size(); i++) ATH_MSG_VERBOSE( "MS cutouts to be processed by Calo:"<< i<<":"<< msCutouts[i].first<<","<<msCutouts[i].second ); + // first member of msCutouts redefines the default central cylinder dimension + if (msCutouts.size()>0) { + m_caloDefaultRadius = msCutouts[0].first; + m_caloDefaultHalflengthZ = msCutouts[0].second; + ATH_MSG_VERBOSE(" Calo central cylinder dimensions adjusted using EnvelopeSvc:"<<m_caloDefaultRadius<<","<< m_caloDefaultHalflengthZ ); + } + + // create dummy ID if not built already + + if (!innerVol) { + Trk::CylinderVolumeBounds* idBounds = new Trk::CylinderVolumeBounds(enclosedInnerSectorRadius, enclosedInnerSectorHalflength); + + Amg::Transform3D* idTr = new Amg::Transform3D(Trk::s_idTransform); + + innerVol = new Trk::TrackingVolume(idTr, idBounds, *m_caloMaterial, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::DummyID"); + + keyDim.push_back(RZPair(enclosedInnerSectorRadius, enclosedInnerSectorHalflength)); + } + + // BEAM PIPE + //std::cout <<"envelope svc : number of BeamPipe Volumes:"<< m_enclosingEnvelopeSvc->getBeamPipeNumVols()<< std::endl; + RZPairVector& bpDefs = m_enclosingEnvelopeSvc->getBeamPipeRZValues(0); + + ATH_MSG_VERBOSE( "BeamPipe envelope definition retrieved:" ); + m_bpCutouts.clear(); + for (unsigned int i=0; i<bpDefs.size(); i++) { + ATH_MSG_VERBOSE( "Rz pair:"<< i<<":"<< bpDefs[i].first<<","<<bpDefs[i].second ); + // beam pipe within calo : pick 10. < R < 200; envEnclosingVolumeHalfZ =< z <= msCutouts.back().second; + if ( bpDefs[i].first > 10. && bpDefs[i].first < 200. && bpDefs[i].second>=envEnclosingVolumeHalfZ && bpDefs[i].second <= msCutouts.back().second ) { + m_bpCutouts.push_back( bpDefs[i] ); + } + if (i>0 && i<4) keyDim.push_back(bpDefs[i]); + } + + // no beam pipe within ID + //if (m_bpCutouts[0].second == envEnclosingVolumeHalfZ && m_bpCutouts[0].first > 0 ) m_bpCutouts[0].first=0.; + // last not needed + if (m_bpCutouts.size()>1 && m_bpCutouts.back().second==m_bpCutouts[m_bpCutouts.size()-2].second) m_bpCutouts.erase(m_bpCutouts.end()-1); + // end beam pipe envelope within Calo + for (unsigned int i=0; i<m_bpCutouts.size(); i++) ATH_MSG_VERBOSE( "Beam pipe dimensions to be used by Calo:"<< i<<":"<< m_bpCutouts[i].first<<","<<m_bpCutouts[i].second ); + + keyDim.push_back(RZPair(m_caloDefaultRadius,m_caloDefaultHalflengthZ)); + + // get the dimensions from the envelope service + //std::cout <<"envelope svc : number of MS Volumes:"<< m_enclosingEnvelopeSvc->getMuonNumVols()<< std::endl; + //RZPairVector& msDefs = m_enclosingEnvelopeSvc->getMuonRZValues(0); + + //ATH_MSG_VERBOSE( "MS envelope definition retrieved:" ); + //for (unsigned int i=0; i<msDefs.size(); i++) ATH_MSG_VERBOSE( "Rz pair:"<< i<<":"<< msDefs[i].first<<","<<msDefs[i].second ); + + + //////////// ---------------- BUILD FROM GEOMODEL ---------------------------- ///////////////////////////////// + + + // PART 1 : Liquid Argon Volumes =========================================================================================== + // get the Tracking Volumes from the LAr Builder + const std::vector<const Trk::TrackingVolume*>* lArVolumes = m_lArVolumeBuilder->trackingVolumes(); + + ATH_MSG_INFO( lArVolumes->size() << " volumes retrieved from " << m_lArVolumeBuilder.name() ); + if (msgLvl(MSG::VERBOSE)){ + ATH_MSG_VERBOSE( "--------------- detailed output ---------------------------------------------------------- " ); + std::vector<const Trk::TrackingVolume*>::const_iterator lArVolIter = lArVolumes->begin(); + std::vector<const Trk::TrackingVolume*>::const_iterator lArVolIterEnd = lArVolumes->end(); + for ( ; lArVolIter != lArVolIterEnd; ++lArVolIter) + if (*lArVolIter) (*lArVolIter)->screenDump(msg(MSG::VERBOSE)) ; + } + + // LAr Barrel part + const Trk::TrackingVolume* solenoid = (*lArVolumes)[0]; + const Trk::TrackingVolume* solenoidlArPresamplerGap = (*lArVolumes)[1]; + const Trk::TrackingVolume* lArBarrelPresampler = (*lArVolumes)[2]; + const Trk::TrackingVolume* lArBarrel = (*lArVolumes)[3]; + + // LAr Positive Endcap part + const Trk::TrackingVolume* lArPositiveMBTS = (*lArVolumes)[4]; + const Trk::TrackingVolume* lArPositiveEndcap = (*lArVolumes)[5]; + const Trk::TrackingVolume* lArPositiveHec = (*lArVolumes)[6]; + const Trk::TrackingVolume* lArPositiveFcal = (*lArVolumes)[7]; + const Trk::TrackingVolume* lArPositiveHecFcalCover = (*lArVolumes)[8]; + // LAr Negative Endcap part + const Trk::TrackingVolume* lArNegativeMBTS = (*lArVolumes)[9]; + const Trk::TrackingVolume* lArNegativeEndcap = (*lArVolumes)[10]; + const Trk::TrackingVolume* lArNegativeHec = (*lArVolumes)[11]; + const Trk::TrackingVolume* lArNegativeFcal = (*lArVolumes)[12]; + const Trk::TrackingVolume* lArNegativeHecFcalCover = (*lArVolumes)[13]; + const Trk::TrackingVolume* lArPosECPresampler = (*lArVolumes)[14]; + const Trk::TrackingVolume* lArNegECPresampler = (*lArVolumes)[15]; + + + // PART 2 : Tile Volumes =========================================================================================== + // get the Tracking Volumes from the Tile Builder + const std::vector<const Trk::TrackingVolume*>* tileVolumes = m_tileVolumeBuilder->trackingVolumes(); + + ATH_MSG_INFO( tileVolumes->size() << " volumes retrieved from " << m_tileVolumeBuilder.name() ); + if (msgLvl(MSG::INFO)){ + ATH_MSG_INFO( "--------------- detailed output ---------------------------------------------------------- " ); + std::vector<const Trk::TrackingVolume*>::const_iterator tileVolIter = tileVolumes->begin(); + std::vector<const Trk::TrackingVolume*>::const_iterator tileVolIterEnd = tileVolumes->end(); + for ( ; tileVolIter != tileVolIterEnd; (*tileVolIter)->screenDump(msg(MSG::VERBOSE)), ++tileVolIter) + ; + } + + // Tile Barrel part + const Trk::TrackingVolume* tileCombined = (*tileVolumes)[0]; + // Tile Positive Extended Part + const Trk::TrackingVolume* tilePositiveExtendedBarrel = (*tileVolumes)[1]; + + const Trk::CylinderVolumeBounds* ebBounds + = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(tilePositiveExtendedBarrel->volumeBounds())); + + double rTileMin = ebBounds ? ebBounds->innerRadius() : 2288.; + double zTileMin = ebBounds ? tilePositiveExtendedBarrel->center().z()-ebBounds->halflengthZ() : 3559.5; + + keyDim.push_back(RZPair(rTileMin,zTileMin)); + for (unsigned int i=0; i<keyDim.size(); i++) { + ATH_MSG_VERBOSE( "key dimensions:"<< i<<":"<< keyDim[i].first<<","<<keyDim[i].second ); + } + + // The Bounds needed for the Gap Volume creation + const Trk::CylinderVolumeBounds* solenoidBounds + = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(solenoid->volumeBounds())); + if (!solenoidBounds) std::abort(); + const Trk::CylinderVolumeBounds* lArBarrelBounds + = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(lArBarrel->volumeBounds())); + if (!lArBarrelBounds) std::abort(); + const Trk::CylinderVolumeBounds* lArPositiveEndcapBounds + = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(lArPositiveEndcap->volumeBounds())); + if (!lArPositiveEndcapBounds) std::abort(); + const Trk::CylinderVolumeBounds* lArNegativeEndcapBounds + = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(lArNegativeEndcap->volumeBounds())); + if (!lArNegativeEndcapBounds) std::abort(); + const Trk::CylinderVolumeBounds* lArPositiveHecBounds + = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(lArPositiveHec->volumeBounds())); + if (!lArPositiveHecBounds) std::abort(); + const Trk::CylinderVolumeBounds* lArPositiveFcalBounds + = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(lArPositiveFcal->volumeBounds())); + if (!lArPositiveFcalBounds) std::abort(); + const Trk::CylinderVolumeBounds* lArNegativeFcalBounds + = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(lArNegativeFcal->volumeBounds())); + if (!lArNegativeFcalBounds) std::abort(); + + const Trk::CylinderVolumeBounds* tileCombinedBounds + = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(tileCombined->volumeBounds())); + if (!tileCombinedBounds) std::abort(); + + // Create the gap volumes ====================================================================== + const Trk::TrackingVolume* lArTileCentralSectorGap = 0; + + //const Trk::TrackingVolume* tilePositiveSectorInnerGap = 0; + const Trk::TrackingVolume* lArPositiveSectorInnerGap = 0; + //const Trk::TrackingVolume* lArTilePositiveSectorGap = 0; + const Trk::TrackingVolume* lArPositiveSectorOuterGap = 0; + const Trk::TrackingVolume* lArPositiveSectorOuterGap0 = 0; + const Trk::TrackingVolume* lArCentralPositiveGap = 0; + + //const Trk::TrackingVolume* tileNegativeSectorInnerGap = 0; + const Trk::TrackingVolume* lArNegativeSectorInnerGap = 0; + //const Trk::TrackingVolume* lArTileNegativeSectorGap = 0; + const Trk::TrackingVolume* lArNegativeSectorOuterGap = 0; + const Trk::TrackingVolume* lArNegativeSectorOuterGap0 = 0; + const Trk::TrackingVolume* lArCentralNegativeGap = 0; + + const Trk::TrackingVolume* trtSolenoidGap = 0; + + double caloPositiveOuterBoundary = tileCombinedBounds->halflengthZ(); + + double lArPositiveOuterBoundary = lArPositiveFcal->center().z(); + lArPositiveOuterBoundary += lArPositiveFcalBounds->halflengthZ(); + + double lArNegativeOuterBoundary = lArNegativeFcal->center().z(); + lArNegativeOuterBoundary -= lArNegativeFcalBounds->halflengthZ(); + + Trk::Material* mAr = new Trk::Material(140.036, 856.32, 39.948, 18., 0.0014); + Trk::Material* mAl = new Trk::Material(88.93, 388.62, 26.98, 13., 0.0027); + //Trk::Material* mFe = new Trk::Material(17.58, 169.68, 55.85, 26., 0.0079); + Trk::Material* mScint = new Trk::Material(424.35, 707.43, 11.16, 5.61, 0.001); // from G4 definition + const Trk::Material* crackMaterial = new Trk::Material(424.35, 707.43, 11.16, 5.61, 0.001); // Scintillator/Glue (G4 def.) + + throwIntoGarbage(mAr); + throwIntoGarbage(mAl); + throwIntoGarbage(mScint); + throwIntoGarbage(crackMaterial); + + // No. 1 + // building dense volume here + Trk::Material tilePositiveSectorInnerGapMaterial = Trk::Material(58., 565., 30.7, 14.6, 0.0025); + + // calo sensitive volume outer radius/z extent defined (for example) here + float caloVolsOuterRadius = tileCombinedBounds->outerRadius(); + float caloVolsExtendZ = caloPositiveOuterBoundary; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // LAr InnerGap sector + beam pipe + + Trk::Material lArSectorInnerGapMaterial = Trk::Material(361., 1370., 14.5, 7., 0.0009); // ??? + + // create beam pipe volumes for InnerGap/MBTS and return their outer radius + float rInnerGapBP=0.; + std::pair<const Trk::TrackingVolume*,const Trk::TrackingVolume*> innerGapBP = createBeamPipeVolumes(keyDim[0].second, + //lArPositiveEndcap->center().z()-lArPositiveEndcapBounds->halflengthZ(), + keyDim.back().second, + "InnerGap", rInnerGapBP); + + double z = 0.5*(keyDim.back().second+keyDim[0].second); + + if (lArPositiveMBTS && lArNegativeMBTS) { + // Disc + const Trk::CylinderVolumeBounds* mbtsBounds + = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(lArPositiveMBTS->volumeBounds())); +#if 0 + if (mbtsBounds && m_caloSurfaceHelper) { // pass ownership + Amg::Transform3D* mbtsNeg = new Amg::Transform3D(Amg::Translation3D(lArNegativeMBTS->center())); + Amg::Transform3D* mbtsPos = new Amg::Transform3D(Amg::Translation3D(lArPositiveMBTS->center())); + m_caloSurfaceHelper->LoadMBTSSurfaces(std::pair<const Trk::Surface*,const Trk::Surface*> + (new Trk::DiscSurface(mbtsNeg,mbtsBounds->innerRadius(),mbtsBounds->outerRadius()), + new Trk::DiscSurface(mbtsPos,mbtsBounds->innerRadius(),mbtsBounds->outerRadius()))); + } +#endif + if (mbtsBounds && m_buildMBTS) { + float rmin = mbtsBounds->innerRadius(); + float rmax = mbtsBounds->outerRadius(); + //float d = mbtsBounds->halflengthZ(); + Trk::DiscBounds* dibo = new Trk::DiscBounds(rmin,rmax); + // MBTS positions + Amg::Transform3D* mbtsNegZpos = new Amg::Transform3D(Amg::Translation3D(lArNegativeMBTS->center())); + Amg::Transform3D* mbtsPosZpos = new Amg::Transform3D(Amg::Translation3D(lArPositiveMBTS->center())); + // create the two Layers ( TODO: add trd surface subarray ) + Trk::DiscLayer* mbtsNegLayer = new Trk::DiscLayer(mbtsNegZpos,dibo, + //mbtsNegLayerSurfArray, + Trk::HomogeneousLayerMaterial(Trk::MaterialProperties(*m_caloMaterial,1.),1.), + 1.); + Trk::DiscLayer* mbtsPosLayer = new Trk::DiscLayer(mbtsPosZpos,dibo->clone(), + //mbtsPosLayerSurfArray, + Trk::HomogeneousLayerMaterial(Trk::MaterialProperties(*m_caloMaterial,1.),1.), + 1.*Gaudi::Units::mm); + + m_mbtsNegLayers=new std::vector<const Trk::Layer*>; + m_mbtsPosLayers=new std::vector<const Trk::Layer*>; + m_mbtsNegLayers->push_back(mbtsNegLayer); + m_mbtsPosLayers->push_back(mbtsPosLayer); + } + } + + // building inner gap + Trk::CylinderVolumeBounds* lArG1Bounds = + new Trk::CylinderVolumeBounds( rInnerGapBP, + //lArPositiveEndcapBounds->outerRadius(), + keyDim[0].first, + 0.5*(keyDim.back().second-keyDim[0].second)); + + Amg::Transform3D* lArG1P = + new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,z))); + lArPositiveSectorInnerGap = new Trk::TrackingVolume(lArG1P, + lArG1Bounds, + lArSectorInnerGapMaterial, + m_mbtsPosLayers, + "Calo::GapVolumes::LAr::PositiveSectorInnerGap"); + + Amg::Transform3D* lArG1N = + new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,-z))); + lArNegativeSectorInnerGap = new Trk::TrackingVolume(lArG1N, + lArG1Bounds->clone(), + lArSectorInnerGapMaterial, + m_mbtsNegLayers, + "Calo::GapVolumes::LAr::NegativeSectorInnerGap"); + + // glue InnerGap with beam pipe volumes + const Trk::TrackingVolume* positiveInnerGap = 0; + if (innerGapBP.first) { + std::vector<const Trk::TrackingVolume*> volsInnerGap; + volsInnerGap.push_back(innerGapBP.first); + volsInnerGap.push_back(lArPositiveSectorInnerGap); + positiveInnerGap = m_trackingVolumeCreator->createContainerTrackingVolume(volsInnerGap, + *m_caloMaterial, + "Calo::Container::PositiveInnerGap"); + } else positiveInnerGap = lArPositiveSectorInnerGap; + + const Trk::TrackingVolume* negativeInnerGap = 0; + if (innerGapBP.second) { + std::vector<const Trk::TrackingVolume*> volsInnerGap; + volsInnerGap.push_back(innerGapBP.second); + volsInnerGap.push_back(lArNegativeSectorInnerGap); + negativeInnerGap = m_trackingVolumeCreator->createContainerTrackingVolume(volsInnerGap, + *m_caloMaterial, + "Calo::Container::NegativeInnerGap"); + } else negativeInnerGap = lArNegativeSectorInnerGap; + + // glue MBTS volumes with ID + std::vector<const Trk::TrackingVolume*> inBufferVolumes; + inBufferVolumes.push_back(negativeInnerGap); + inBufferVolumes.push_back(innerVol); + inBufferVolumes.push_back(positiveInnerGap); + + const Trk::TrackingVolume* inDetEnclosed = m_trackingVolumeCreator->createContainerTrackingVolume(inBufferVolumes, + *m_caloMaterial, + "Calo::Container::EnclosedInnerDetector"); + + + ATH_MSG_DEBUG( " Inner detector enclosed (MBTS volumes)" ); + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // LAr endcap sector including the beam pipe + + // create beam pipe volumes for Endcap and return their outer radius + float rEndcapBP=0.; + std::pair<const Trk::TrackingVolume*,const Trk::TrackingVolume*> endcapBP = createBeamPipeVolumes( + keyDim.back().second, + lArPositiveEndcap->center().z()+lArPositiveEndcapBounds->halflengthZ(), + "Endcap", rEndcapBP); + + // build lAr vessel around EC Presampler + const Trk::CylinderVolumeBounds* ecpBounds + = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(lArPosECPresampler->volumeBounds())); + if (!ecpBounds) std::abort(); + + float ecpHz = ecpBounds->halflengthZ(); + float ecpRmin = ecpBounds->innerRadius(); + float ecpRmax = ecpBounds->outerRadius(); + + Amg::Transform3D* ecpPos=new Amg::Transform3D(lArPosECPresampler->transform()); + Amg::Transform3D* ecpNeg=new Amg::Transform3D(lArNegECPresampler->transform()); + + Trk::CylinderVolumeBounds* ecpUpBounds = new Trk::CylinderVolumeBounds(ecpRmax, keyDim.back().first, ecpHz); + Trk::CylinderVolumeBounds* ecpDownBounds = new Trk::CylinderVolumeBounds(rEndcapBP, ecpRmin, ecpHz); + + const Trk::TrackingVolume* ecPresamplerCoverPos = new Trk::TrackingVolume(ecpPos,ecpUpBounds, *mAl, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::PositiveECPresamplerCover"); + const Trk::TrackingVolume* ecPresamplerCoverNeg = new Trk::TrackingVolume(ecpNeg,ecpUpBounds->clone(), *mAl, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::NegativeECPresamplerCover"); + const Trk::TrackingVolume* ecPresamplerInnerPos = new Trk::TrackingVolume(new Amg::Transform3D(*ecpPos),ecpDownBounds, *mAl, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::PositiveECPresamplerInner"); + const Trk::TrackingVolume* ecPresamplerInnerNeg = new Trk::TrackingVolume(new Amg::Transform3D(*ecpNeg),ecpDownBounds->clone(), + *mAl, dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::NegativeECPresamplerInner"); + + // glue EC presampler radially + std::vector<const Trk::TrackingVolume*> volsECP; + volsECP.push_back(ecPresamplerInnerPos); + volsECP.push_back(lArPosECPresampler); + volsECP.push_back(ecPresamplerCoverPos); + const Trk::TrackingVolume* positiveECP = m_trackingVolumeCreator->createContainerTrackingVolume(volsECP, + *m_caloMaterial, + "Calo::Container::PositiveECPresamplerR"); + std::vector<const Trk::TrackingVolume*> volsECN; + volsECN.push_back(ecPresamplerInnerNeg); + volsECN.push_back(lArNegECPresampler); + volsECN.push_back(ecPresamplerCoverNeg); + const Trk::TrackingVolume* negativeECP = m_trackingVolumeCreator->createContainerTrackingVolume(volsECN, + *m_caloMaterial, + "Calo::Container::NegativeECPresamplerR"); + + // add surrounding buffers + z = lArPosECPresampler->center().z()-ecpHz; + float z1 = lArPosECPresampler->center().z()+ecpHz; + float z2 = lArPositiveEndcap->center().z()-lArPositiveEndcapBounds->halflengthZ(); + Amg::Transform3D* ecIPos = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0., 0.5*(z+keyDim.back().second)))); + Amg::Transform3D* ecINeg = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,-0.5*(z+keyDim.back().second)))); + Trk::CylinderVolumeBounds* ecpIBounds = new Trk::CylinderVolumeBounds(rEndcapBP, keyDim.back().first,0.5*(z-keyDim.back().second)); + Amg::Transform3D* ecOPos = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0., 0.5*(z1+z2)))); + Amg::Transform3D* ecONeg = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,-0.5*(z1+z2)))); + Trk::CylinderVolumeBounds* ecpOBounds = new Trk::CylinderVolumeBounds(rEndcapBP, keyDim.back().first,0.5*(z2-z1)); + + const Trk::TrackingVolume* ecPresamplerInPos = new Trk::TrackingVolume(ecIPos,ecpIBounds, *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::PositiveECPresamplerIn"); + const Trk::TrackingVolume* ecPresamplerInNeg = new Trk::TrackingVolume(ecINeg,ecpIBounds->clone(), *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::NegativeECPresamplerIn"); + const Trk::TrackingVolume* ecPresamplerOutPos = new Trk::TrackingVolume(ecOPos,ecpOBounds, *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::PositiveECPresamplerOut"); + const Trk::TrackingVolume* ecPresamplerOutNeg = new Trk::TrackingVolume(ecONeg,ecpOBounds->clone(), + *mAr, dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::NegativeECPresamplerOut"); + + // glue EC presampler in z + std::vector<const Trk::TrackingVolume*> volECP; + volECP.push_back(ecPresamplerInPos); + volECP.push_back(positiveECP); + volECP.push_back(ecPresamplerOutPos); + const Trk::TrackingVolume* positiveEP = m_trackingVolumeCreator->createContainerTrackingVolume(volECP, + *m_caloMaterial, + "Calo::Container::PositiveECPresampler"); + std::vector<const Trk::TrackingVolume*> volECN; + volECN.push_back(ecPresamplerOutNeg); + volECN.push_back(negativeECP); + volECN.push_back(ecPresamplerInNeg); + const Trk::TrackingVolume* negativeEP = m_trackingVolumeCreator->createContainerTrackingVolume(volECN, + *m_caloMaterial, + "Calo::Container::NegativeECPresampler"); + + // build lAr vessel around EMEC + ecpHz = lArPositiveEndcapBounds->halflengthZ(); + ecpRmin = lArPositiveEndcapBounds->innerRadius(); + ecpRmax = lArPositiveEndcapBounds->outerRadius(); + + Amg::Transform3D* ecPos=new Amg::Transform3D(lArPositiveEndcap->transform()); + Amg::Transform3D* ecNeg=new Amg::Transform3D(lArNegativeEndcap->transform()); + + Trk::CylinderVolumeBounds* ecUpBounds = new Trk::CylinderVolumeBounds(ecpRmax, keyDim.back().first, ecpHz); + Trk::CylinderVolumeBounds* ecDownBounds = new Trk::CylinderVolumeBounds(rEndcapBP, ecpRmin, ecpHz); + + const Trk::TrackingVolume* ecCoverPos = new Trk::TrackingVolume(ecPos,ecUpBounds, *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::PositiveEndcapCover"); + const Trk::TrackingVolume* ecCoverNeg = new Trk::TrackingVolume(ecNeg,ecUpBounds->clone(), *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::NegativeEndcapCover"); + const Trk::TrackingVolume* ecInnerPos = new Trk::TrackingVolume(new Amg::Transform3D(*ecPos),ecDownBounds, *mAl, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::PositiveEndcapInner"); + const Trk::TrackingVolume* ecInnerNeg = new Trk::TrackingVolume(new Amg::Transform3D(*ecNeg),ecDownBounds->clone(), + *mAl, dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::NegativeEndcapInner"); + + // glue EMEC radially + std::vector<const Trk::TrackingVolume*> volsEC; + volsEC.push_back(ecInnerPos); + volsEC.push_back(lArPositiveEndcap); + volsEC.push_back(ecCoverPos); + const Trk::TrackingVolume* positiveEC = m_trackingVolumeCreator->createContainerTrackingVolume(volsEC, + *m_caloMaterial, + "Calo::Container::PositiveEndcapR"); + std::vector<const Trk::TrackingVolume*> volsEN; + volsEN.push_back(ecInnerNeg); + volsEN.push_back(lArNegativeEndcap); + volsEN.push_back(ecCoverNeg); + const Trk::TrackingVolume* negativeEC = m_trackingVolumeCreator->createContainerTrackingVolume(volsEN, + *m_caloMaterial, + "Calo::Container::NegativeEndcapR"); + + // glue presampler with EMEC + std::vector<const Trk::TrackingVolume*> volEEP; + volEEP.push_back(positiveEP); + volEEP.push_back(positiveEC); + const Trk::TrackingVolume* positiveEEP = m_trackingVolumeCreator->createContainerTrackingVolume(volEEP, + *m_caloMaterial, + "Calo::Container::PositiveEMEC"); + std::vector<const Trk::TrackingVolume*> volEEN; + volEEN.push_back(negativeEC); + volEEN.push_back(negativeEP); + const Trk::TrackingVolume* negativeEEP = m_trackingVolumeCreator->createContainerTrackingVolume(volEEN, + *m_caloMaterial, + "Calo::Container::NegativeEMEC"); + + // glue EMEC sector with beam pipe volumes + + std::vector<const Trk::TrackingVolume*> volsEndcapPos; + if (endcapBP.first) volsEndcapPos.push_back(endcapBP.first); + volsEndcapPos.push_back(positiveEEP); + + std::unique_ptr<const Trk::TrackingVolume> positiveEndcap + (m_trackingVolumeCreator->createContainerTrackingVolume(volsEndcapPos, + *m_caloMaterial, + "Calo::Container::PositiveEndcap")); + + std::vector<const Trk::TrackingVolume*> volsEndcapNeg; + if (endcapBP.second) volsEndcapNeg.push_back(endcapBP.second); + volsEndcapNeg.push_back(negativeEEP); + + std::unique_ptr<const Trk::TrackingVolume> negativeEndcap + (m_trackingVolumeCreator->createContainerTrackingVolume(volsEndcapNeg, + *m_caloMaterial, + "Calo::Container::NegativeEndcap")); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Hec sector + beam pipe + lAr cover + + // create beam pipe volumes for Hec and return their outer radius + float rHecBP=0.; + std::pair<const Trk::TrackingVolume*,const Trk::TrackingVolume*> hecBP = createBeamPipeVolumes( + lArPositiveHec->center().z()-lArPositiveHecBounds->halflengthZ(), + lArPositiveHec->center().z()+lArPositiveHecBounds->halflengthZ(), + "Hec", rHecBP); + // HecInnerGap (new gap volume ) + Trk::Material lArHecInnerGapMaterial = Trk::Material(390., 1223., 18.,9., 0.0014); + + // create the Bounds + Trk::CylinderVolumeBounds* lArHecInnerGapBounds = new Trk::CylinderVolumeBounds(rHecBP, + lArPositiveHecBounds->innerRadius(), + lArPositiveHecBounds->halflengthZ() ); + + Amg::Transform3D* lArHecPos = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,lArPositiveHec->center().z()))); + Amg::Transform3D* lArHecNeg = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,lArNegativeHec->center().z()))); + + const Trk::TrackingVolume* lArPositiveHecInnerGap = new Trk::TrackingVolume(lArHecPos,lArHecInnerGapBounds , + *mAl, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::PositiveHecInnerGap"); + + const Trk::TrackingVolume* lArNegativeHecInnerGap = new Trk::TrackingVolume(lArHecNeg,lArHecInnerGapBounds->clone() , + *mAl, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::NegativeHecInnerGap"); + // create the Bounds + Trk::CylinderVolumeBounds* lArHecOuterGapBounds = new Trk::CylinderVolumeBounds(lArPositiveHecBounds->outerRadius(), + keyDim.back().first, + lArPositiveHecBounds->halflengthZ() ); + + const Trk::TrackingVolume* lArPositiveHecOuterGap = new Trk::TrackingVolume(new Amg::Transform3D(*lArHecPos), + lArHecOuterGapBounds , + *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::PositiveHecOuterGap"); + + const Trk::TrackingVolume* lArNegativeHecOuterGap = new Trk::TrackingVolume(new Amg::Transform3D(*lArHecNeg), + lArHecOuterGapBounds->clone() , + *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::NegativeHecOuterGap"); + + // glue Hec sector with beam pipe volumes + + std::vector<const Trk::TrackingVolume*> volsHecPos; + if (hecBP.first) volsHecPos.push_back(hecBP.first); + volsHecPos.push_back(lArPositiveHecInnerGap); + volsHecPos.push_back(lArPositiveHec); + volsHecPos.push_back(lArPositiveHecOuterGap); + + std::unique_ptr<const Trk::TrackingVolume> positiveHec + (m_trackingVolumeCreator->createContainerTrackingVolume(volsHecPos, + *m_caloMaterial, + "Calo::Container::PositiveHec")); + + std::vector<const Trk::TrackingVolume*> volsHecNeg; + if (hecBP.second) volsHecNeg.push_back(hecBP.second); + volsHecNeg.push_back(lArNegativeHecInnerGap); + volsHecNeg.push_back(lArNegativeHec); + volsHecNeg.push_back(lArNegativeHecOuterGap); + + std::unique_ptr<const Trk::TrackingVolume> negativeHec + (m_trackingVolumeCreator->createContainerTrackingVolume(volsHecNeg, + *m_caloMaterial, + "Calo::Container::NegativeHec")); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Fcal sector + beam pipe + lAr cover + + // create beam pipe volumes for Fcal and return their outer radius + float rFcalBP=0.; + std::pair<const Trk::TrackingVolume*,const Trk::TrackingVolume*> fcalBP = createBeamPipeVolumes( + lArPositiveFcal->center().z()-lArPositiveFcalBounds->halflengthZ(), + lArPositiveFcal->center().z()+lArPositiveFcalBounds->halflengthZ(), + "Fcal", rFcalBP); + // FcalInnerGap (new gap volume ) + //Trk::Material lArFcalInnerGapMaterial = Trk::Material(390., 1223., 40.,18., 0.0014); + + + if ( rFcalBP > lArPositiveFcalBounds->innerRadius()) { + ATH_MSG_ERROR("PROBLEM : beam pipe collide with Fcal:"<< rFcalBP <<">" << lArPositiveFcalBounds->innerRadius()<<", abort" ); + // create dummy infinite IOV Range + EventIDRange range; + return std::pair<EventIDRange, const Trk::TrackingGeometry*>(range,0); + + } + + // create the Bounds + Trk::CylinderVolumeBounds* lArFcalInnerGapBounds = new Trk::CylinderVolumeBounds(rFcalBP, + lArPositiveFcalBounds->innerRadius(), + lArPositiveFcalBounds->halflengthZ() ); + + Amg::Transform3D* lArFcalPos = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,lArPositiveFcal->center().z()))); + Amg::Transform3D* lArFcalNeg = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,lArNegativeFcal->center().z()))); + + const Trk::TrackingVolume* lArPositiveFcalInnerGap = new Trk::TrackingVolume(lArFcalPos,lArFcalInnerGapBounds , + *mAl, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::PositiveFcalInnerGap"); + + const Trk::TrackingVolume* lArNegativeFcalInnerGap = new Trk::TrackingVolume(lArFcalNeg,lArFcalInnerGapBounds->clone() , + *mAl, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::NegativeFcalInnerGap"); + + + // create the Bounds + Trk::CylinderVolumeBounds* lArFcalOuterGapBounds = new Trk::CylinderVolumeBounds(lArPositiveHecBounds->outerRadius(), + keyDim.back().first, + lArPositiveFcalBounds->halflengthZ() ); + + const Trk::TrackingVolume* lArPositiveFcalOuterGap = new Trk::TrackingVolume(new Amg::Transform3D(*lArFcalPos), + lArFcalOuterGapBounds , + *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::PositiveFcalOuterGap"); + + const Trk::TrackingVolume* lArNegativeFcalOuterGap = new Trk::TrackingVolume(new Amg::Transform3D(*lArFcalNeg), + lArFcalOuterGapBounds->clone() , + *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::NegativeFcalOuterGap"); + + // glue Fcal sector with beam pipe volumes + + std::vector<const Trk::TrackingVolume*> volsFcalPos; + if (fcalBP.first) volsFcalPos.push_back(fcalBP.first); + volsFcalPos.push_back(lArPositiveFcalInnerGap); + volsFcalPos.push_back(lArPositiveFcal); + volsFcalPos.push_back(lArPositiveHecFcalCover); + volsFcalPos.push_back(lArPositiveFcalOuterGap); + + std::unique_ptr<const Trk::TrackingVolume> positiveFcal + (m_trackingVolumeCreator->createContainerTrackingVolume(volsFcalPos, + *m_caloMaterial, + "Calo::Container::PositiveFcal")); + + std::vector<const Trk::TrackingVolume*> volsFcalNeg; + if (fcalBP.second) volsFcalNeg.push_back(fcalBP.second); + volsFcalNeg.push_back(lArNegativeFcalInnerGap); + volsFcalNeg.push_back(lArNegativeFcal); + volsFcalNeg.push_back(lArNegativeHecFcalCover); + volsFcalNeg.push_back(lArNegativeFcalOuterGap); + + std::unique_ptr<const Trk::TrackingVolume> negativeFcal + (m_trackingVolumeCreator->createContainerTrackingVolume(volsFcalNeg, + *m_caloMaterial, + "Calo::Container::NegativeFcal")); + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Outer endcap sector + beam pipe + + // create beam pipe volumes for Outer sector and return their outer radius + float rOutBP=0.; + std::pair<const Trk::TrackingVolume*,const Trk::TrackingVolume*> outBP = createBeamPipeVolumes( lArPositiveOuterBoundary, + caloPositiveOuterBoundary, + "Outer", rOutBP); + + Trk::Material lArSectorOuterGapMat = Trk::Material(20.5, 723., 64., 28., 0.0084); + + Trk::CylinderVolumeBounds* lArSectorOuterG0Bounds = new Trk::CylinderVolumeBounds( rOutBP, 430., + //lArPositiveEndcapBounds->outerRadius(), + 0.5*(caloPositiveOuterBoundary-lArPositiveOuterBoundary)); + + Trk::CylinderVolumeBounds* lArSectorOuterG1Bounds = new Trk::CylinderVolumeBounds( 430., keyDim.back().first, + //lArPositiveEndcapBounds->outerRadius(), + 0.5*(caloPositiveOuterBoundary-lArPositiveOuterBoundary)); + + z = 0.5*(caloPositiveOuterBoundary+lArPositiveOuterBoundary); + + Amg::Transform3D* lArSecOutG1P = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,z))); + Amg::Transform3D* lArSecOutG0P = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,z))); + + lArPositiveSectorOuterGap0 = new Trk::TrackingVolume(lArSecOutG0P, lArSectorOuterG0Bounds, + lArSectorOuterGapMat, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::PositiveSectorOuterGap0"); + + lArPositiveSectorOuterGap = new Trk::TrackingVolume(lArSecOutG1P, lArSectorOuterG1Bounds, + *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::PositiveSectorOuterGap"); + + Amg::Transform3D* lArSecOutG1N = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,-z))); + Amg::Transform3D* lArSecOutG0N = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,-z))); + + lArNegativeSectorOuterGap0 = new Trk::TrackingVolume(lArSecOutG0N, lArSectorOuterG0Bounds->clone(), + lArSectorOuterGapMat, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::NegativeSectorOuterGap0"); + + lArNegativeSectorOuterGap = new Trk::TrackingVolume(lArSecOutG1N, lArSectorOuterG1Bounds->clone(), + *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LAr::NegativeSectorOuterGap"); + + // glue OuterGap with beam pipe volumes + std::vector<const Trk::TrackingVolume*> volsOuterGapP; + if (outBP.first) volsOuterGapP.push_back(outBP.first); + volsOuterGapP.push_back(lArPositiveSectorOuterGap0); + volsOuterGapP.push_back(lArPositiveSectorOuterGap); + std::unique_ptr<const Trk::TrackingVolume> positiveOuterGap + (m_trackingVolumeCreator->createContainerTrackingVolume(volsOuterGapP, + *m_caloMaterial, + "Calo::Container::PositiveOuterGap")); + + std::vector<const Trk::TrackingVolume*> volsOuterGapN; + if (outBP.second) volsOuterGapN.push_back(outBP.second); + volsOuterGapN.push_back(lArNegativeSectorOuterGap0); + volsOuterGapN.push_back(lArNegativeSectorOuterGap); + std::unique_ptr<const Trk::TrackingVolume> negativeOuterGap + (m_trackingVolumeCreator->createContainerTrackingVolume(volsOuterGapN, + *m_caloMaterial, + "Calo::Container::NegativeOuterGap")); + + ATH_MSG_DEBUG( "Endcap volumes ready" ); + + // ++ (ii) lArNegativeSector + const Trk::TrackingVolume* lArNegativeSector = 0; + // +++ has 4 sub volumes in Z + std::vector<const Trk::TrackingVolume*> lArNegativeSectorVolumes; + // +++ (A) -> Outer sector + lArNegativeSectorVolumes.push_back(negativeOuterGap.release()); + // +++ (B) -> Fcal sector + lArNegativeSectorVolumes.push_back(negativeFcal.release()); + // +++ (C) -> Hec sector + lArNegativeSectorVolumes.push_back(negativeHec.release()); + // +++ (D) -> Endcap sector + lArNegativeSectorVolumes.push_back(negativeEndcap.release()); + // +++ all exists : create super volume (ii) + lArNegativeSector = m_trackingVolumeCreator->createContainerTrackingVolume( lArNegativeSectorVolumes, + *m_caloMaterial, + "Calo::LAr::Container::NegativeSector"); + + // ++ (ii) lArPositiveSector + const Trk::TrackingVolume* lArPositiveSector = 0; + // +++ has 4 sub volumes in Z + std::vector<const Trk::TrackingVolume*> lArPositiveSectorVolumes; + // +++ (A) -> Endcap sector + lArPositiveSectorVolumes.push_back(positiveEndcap.release()); + // +++ (B) -> Hec sector + lArPositiveSectorVolumes.push_back(positiveHec.release()); + // +++ (C) -> Fcal sector + lArPositiveSectorVolumes.push_back(positiveFcal.release()); + // +++ (D) -> OuterGap + lArPositiveSectorVolumes.push_back(positiveOuterGap.release()); + // +++ all exists : create super volume (ii) + lArPositiveSector = m_trackingVolumeCreator->createContainerTrackingVolume( lArPositiveSectorVolumes, + *m_caloMaterial, + "Calo::LAr::Container::PositiveSector"); + + ////////////////////////////////////////////////////////////////////////////////////// + // central LAr barrel + // + // solenoid gap + Trk::CylinderVolumeBounds* trtSolGapBounds = new Trk::CylinderVolumeBounds( keyDim[0].first, + solenoidBounds->innerRadius(), + solenoidBounds->halflengthZ()); + + // solenoid gap is not completely empty + Trk::Material solGapMat(535.,2871.,18.6,9.1,0.00038); + + + trtSolenoidGap = new Trk::TrackingVolume(0, + trtSolGapBounds, + solGapMat, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::SolenoidGap"); + + Trk::CylinderVolumeBounds* lArTileCentralG1Bounds = new Trk::CylinderVolumeBounds( lArBarrelBounds->outerRadius(), + tileCombinedBounds->innerRadius(), + lArBarrelBounds->halflengthZ()); + + + + lArTileCentralSectorGap = new Trk::TrackingVolume(0, lArTileCentralG1Bounds, + *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LArTileCentralSectorGap"); + + + const Trk::TrackingVolume* lArCentralBarrelSector = 0; + // ++ has 6 sub volumes in R + std::vector<const Trk::TrackingVolume*> lArCentralBarrelSectorVolumes; + // ++++ (a) -> solenoid gap + lArCentralBarrelSectorVolumes.push_back(trtSolenoidGap); + // ++++ (b) -> solenoid (exists already) + lArCentralBarrelSectorVolumes.push_back(solenoid); + // ++++ (c) -> solenoidlArPresamplerGap (exists already) + lArCentralBarrelSectorVolumes.push_back(solenoidlArPresamplerGap); + // ++++ (d) -> lArBarrelPresampler (exists already) + lArCentralBarrelSectorVolumes.push_back(lArBarrelPresampler); + // ++++ (e) -> lArBarrel (exists already) + lArCentralBarrelSectorVolumes.push_back(lArBarrel); + // ++++ (f) -> lArTile gap + lArCentralBarrelSectorVolumes.push_back(lArTileCentralSectorGap); + // ++++ all sub volumes exist: build the super volume + lArCentralBarrelSector = m_trackingVolumeCreator->createContainerTrackingVolume( + lArCentralBarrelSectorVolumes, + *m_caloMaterial, + "Calo::Containers::LAr::CentralBarrelSector", + false, true); + ///////////////////////////////////////////////////////////////////////////////////// + // side buffers + // the Tile Crack volume (TileGap3, enum 17) inserted here + // binned material for Crack : steering in binEta + // TODO turn into 2D binned array + std::vector<const Trk::IdentifiedMaterial*> matCrack; + // layer material can be adjusted here + int baseID = Trk::GeometrySignature(Trk::Calo)*1000 + 17; + matCrack.push_back(new std::pair<const Trk::Material*,int>(mScint,baseID)); + matCrack.push_back(new std::pair<const Trk::Material*,int>(m_caloMaterial,-1)); + matCrack.push_back(new std::pair<const Trk::Material*,int>(mAl,-1)); + // + Trk::BinUtility* bun = new Trk::BinUtility(3,-1.8,-1.2,Trk::open,Trk::binEta); + Trk::BinUtility* bup = new Trk::BinUtility(3, 1.2,1.8,Trk::open,Trk::binEta); + // array of indices + std::vector<std::vector<size_t> > indexP; + std::vector<std::vector<size_t> > indexN; + // binned material for LAr : layer depth per eta bin + std::vector< Trk::BinUtility*> layDN(bun->bins()); + std::vector< Trk::BinUtility*> layUP(bup->bins()); + double crackZ1 = 3532.; + double crackZ2 = 3540.; + // construct bin utilities + std::vector<float> steps; + for (unsigned int i=0; i< bup->bins(); i++) { + steps.clear(); + std::vector<size_t> indx; indx.clear(); + steps.push_back(crackZ1); + indx.push_back( i<2 ? 0 : 1); + steps.push_back(crackZ2); + indx.push_back(2); + steps.push_back(keyDim.back().second); + Trk::BinUtility* zBU = new Trk::BinUtility(steps, Trk::open, Trk::binZ); + layUP[i] = zBU; + indexP.push_back(indx); + } + + const Trk::BinnedMaterial* crackBinPos = new Trk::BinnedMaterial(crackMaterial,bup,layUP,indexP,matCrack); + + Amg::Transform3D* align=0; + + Trk::CylinderVolumeBounds* crackBoundsPos = new Trk::CylinderVolumeBounds( keyDim[0].first, + tileCombinedBounds->innerRadius(), + 0.5*(keyDim.back().second-crackZ1)); + z = 0.5*(keyDim.back().second+crackZ1); + Amg::Transform3D* crackPosTransform = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,z))); + + const Trk::AlignableTrackingVolume* crackPos = new Trk::AlignableTrackingVolume(crackPosTransform,align, + crackBoundsPos, + crackBinPos, + 17, + "Calo::Detectors::Tile::CrackPos"); + + for (unsigned int i=0; i< bun->bins(); i++) { + steps.clear(); + std::vector<size_t> indx; indx.clear(); + steps.push_back(-keyDim.back().second); + indx.push_back(2); + steps.push_back(-crackZ2); + indx.push_back( i>0 ? 0 : 1); + steps.push_back(-crackZ1); + Trk::BinUtility* zBU = new Trk::BinUtility(steps, Trk::open, Trk::binZ); + layDN[i] = zBU; + indexN.push_back(indx); + } + + const Trk::BinnedMaterial* crackBinNeg = new Trk::BinnedMaterial(crackMaterial,bun,layDN,indexN,matCrack); + + align=0; + + Amg::Transform3D* crackNegTransform = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,-z))); + + const Trk::AlignableTrackingVolume* crackNeg = new Trk::AlignableTrackingVolume(crackNegTransform,align, + crackBoundsPos->clone(), + crackBinNeg, + 17, + "Calo::Detectors::Tile::CrackNeg"); + //// + + Trk::CylinderVolumeBounds* lArCentralG1Bounds = new Trk::CylinderVolumeBounds( keyDim[0].first, + tileCombinedBounds->innerRadius(), + 0.5*(crackZ1-lArBarrelBounds->halflengthZ())); + + z = 0.5*(crackZ1+lArBarrelBounds->halflengthZ()); + Amg::Transform3D* lArCentralG1P = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,z))); + + + lArCentralPositiveGap = new Trk::TrackingVolume(lArCentralG1P, lArCentralG1Bounds, + *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LArCentralPositiveGap"); + + Amg::Transform3D* lArCentralG1N = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,-z))); + + lArCentralNegativeGap = new Trk::TrackingVolume(lArCentralG1N, lArCentralG1Bounds->clone(), + *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::LArCentralNegativeGap"); + + // glue laterally + const Trk::TrackingVolume* lArCentralSector = 0; + // ++ has 5 sub volumes in z + std::vector<const Trk::TrackingVolume*> lArCentralSectorVolumes; + // ++++ (a) -> negative crack + lArCentralSectorVolumes.push_back(crackNeg); + // ++++ (b) -> negative gap + lArCentralSectorVolumes.push_back(lArCentralNegativeGap); + // ++++ (c) -> central barrel + lArCentralSectorVolumes.push_back(lArCentralBarrelSector); + // ++++ (d) -> positive gap + lArCentralSectorVolumes.push_back(lArCentralPositiveGap); + // ++++ (e) -> positive crack + lArCentralSectorVolumes.push_back(crackPos); + // ++++ all sub volumes exist: build the super volume + lArCentralSector = m_trackingVolumeCreator->createContainerTrackingVolume( + lArCentralSectorVolumes, + *m_caloMaterial, + "Calo::Containers::LAr::CentralSector"); + + // glue with ID sector + const Trk::TrackingVolume* caloCentralSector = 0; + // ++ has 2 sub volumes in R + std::vector<const Trk::TrackingVolume*> caloCentralSectorVolumes; + // ++++ (a) -> ID sector + caloCentralSectorVolumes.push_back(inDetEnclosed); + // ++++ (b) -> LAr sector + caloCentralSectorVolumes.push_back(lArCentralSector); + // ++++ all sub volumes exist: build the super volume + caloCentralSector = m_trackingVolumeCreator->createContainerTrackingVolume( + caloCentralSectorVolumes, + *m_caloMaterial, + "Calo::Containers::CaloCentralSector"); + + //std::cout <<"Combined LAr sector ready"<< std::endl; + ////////////////////////////////////////////////////////////////////// + + + // glue laterally with endcaps + const Trk::TrackingVolume* lArCombined = 0; + // ++ has 3 sub volumes in z + std::vector<const Trk::TrackingVolume*> lArCombinedVolumes; + // ++++ (a) -> negative endcap + lArCombinedVolumes.push_back(lArNegativeSector); + // ++++ (b) -> barrel + lArCombinedVolumes.push_back(caloCentralSector); + // ++++ (a) -> positive endcap + lArCombinedVolumes.push_back(lArPositiveSector); + // ++++ all sub volumes exist: build the super volume + lArCombined = m_trackingVolumeCreator->createContainerTrackingVolume( + lArCombinedVolumes, + *m_caloMaterial, + "Calo::Containers::LAr::Combined"); + + //std::cout <<"Combined LAr ready " << std::endl; + + // glue with LAr sector + const Trk::TrackingVolume* caloCombined = 0; + // ++ has 2 sub volumes in R + std::vector<const Trk::TrackingVolume*> caloVolumes; + // ++++ (a) -> LAr sector + caloVolumes.push_back(lArCombined); + // ++++ (b) -> Tile sector + caloVolumes.push_back(tileCombined); + // ++++ all sub volumes exist: build the super volume + caloCombined = m_trackingVolumeCreator->createContainerTrackingVolume( + caloVolumes, + *m_caloMaterial, + "Calo::Containers::CombinedCalo"); + + //std::cout <<"Combined Calo ready"<< std::endl; + + /////////////////////////////////////////////////////////////////////////////////////////////// + + // build the radial buffer volume to synchronize the radial envelope dimensions + const Trk::TrackingVolume* centralBuffer = 0; + const Trk::TrackingVolume* ecPosBuffer = 0; + const Trk::TrackingVolume* ecNegBuffer = 0; + + if ( caloVolsOuterRadius > m_caloDefaultRadius ) { + ATH_MSG_VERBOSE( "Calo volumes exceeds envelope radius: adjusting envelope (de-synchronizing...)" ); + m_caloDefaultRadius = caloVolsOuterRadius; + } + + if ( caloVolsOuterRadius < m_caloDefaultRadius ) { + ATH_MSG_VERBOSE( "Build radial buffer to synchronize the boundaries in between R "<< caloVolsOuterRadius<<" and "<< m_caloDefaultRadius ); + + Trk::CylinderVolumeBounds* centralSynBounds = new Trk::CylinderVolumeBounds(caloVolsOuterRadius, + m_caloDefaultRadius, + caloVolsExtendZ); + centralBuffer = new Trk::TrackingVolume(0, centralSynBounds, + *m_caloMaterial, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::EnvelopeBuffer"); + } + + if ( caloVolsExtendZ < m_caloDefaultHalflengthZ ) { + ATH_MSG_VERBOSE( "Build longitudinal buffers to synchronize the boundaries in between Z "<< caloVolsExtendZ<<" and "<< m_caloDefaultHalflengthZ ); + + Trk::CylinderVolumeBounds* endcapSynBounds = new Trk::CylinderVolumeBounds(0., m_caloDefaultRadius, + 0.5*(m_caloDefaultHalflengthZ-caloVolsExtendZ)); + // endcap buffers not empty + Trk::Material ecBuffMat(53./0.38, 355./0.38, 20., 10., 0.0053*pow(0.38,3)); + + float zPos = 0.5*(m_caloDefaultHalflengthZ+caloVolsExtendZ); + ecPosBuffer = new Trk::TrackingVolume(new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,zPos))), + endcapSynBounds, + *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::PosECBuffer"); + + ecNegBuffer = new Trk::TrackingVolume(new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,-zPos))), + endcapSynBounds->clone(), + *mAr, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::NegECBuffer"); + } + + ATH_MSG_VERBOSE( "All gap volumes for the Calorimeter created. Starting to build Volume Hiearchy." ); + + ///////////////////////////////////////////////////////////////////////////////////////////////// + + ATH_MSG_VERBOSE( "Resolve MS cutouts:" ); + + // resolve number of additional cutout volumes + int nCutVol = 0; + std::vector<float> zCutStep; + std::vector<float> rCutStep; + if (msCutouts.size()>1) { + zCutStep.push_back(msCutouts[0].second); + rCutStep.push_back(msCutouts[0].first); + for (unsigned int i=1; i<msCutouts.size(); i++) { + if (msCutouts[i].second == zCutStep.back()) rCutStep.push_back(msCutouts[i].first); + else zCutStep.push_back(msCutouts[i].second); + } + nCutVol = zCutStep.size()-1; + } + if (nCutVol>0) ATH_MSG_VERBOSE( nCutVol << " MS cutout volume(s) required " ); + + std::vector<const Trk::TrackingVolume*> forwardCutoutVols; + std::vector<const Trk::TrackingVolume*> backwardCutoutVols; + + // cutout region not empty + std::vector<Trk::Material> cutOutMat; + cutOutMat.push_back(Trk::Material(19.9, 213., 50., 23., 0.0065)); // 3.5 Fe + 1 Ar : verify + cutOutMat.push_back(*m_caloMaterial); + //cutOutMat.push_back(Trk::Material(18.74, 200.9, 52.36, 24.09, 0.0069)); + + if (nCutVol>0) { + // loop over zCutStep, rCutStep[0] gives the fixed outer radius, rCutStep[i] the cutout radius for ith volume + float rout = rCutStep[0]; + float zlow = zCutStep[0]; + for (unsigned int i=1; i<zCutStep.size(); i++) { + float zup = zCutStep[i]; + float rcut = rCutStep[i]; + std::stringstream ss; + ss << i; + // get beam pipe volumes + float rCutOutBP = 0.; + std::pair<const Trk::TrackingVolume*,const Trk::TrackingVolume*> cutOutBP = createBeamPipeVolumes(zlow,zup, + "CutOuts"+ss.str(), rCutOutBP); + + // build inner part ( -> Calo ) + unsigned int mindex = i>1 ? 1 : i; + + Trk::CylinderVolumeBounds* cutInBounds = new Trk::CylinderVolumeBounds( rCutOutBP,rcut, 0.5*(zup-zlow)); + const Trk::TrackingVolume* caloInPos = new Trk::TrackingVolume(new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,0.5*(zup+zlow)))), + cutInBounds, + cutOutMat[mindex], + dummyLayers, dummyVolumes, + "Calo::GapVolumes::CaloPositiveCutIn"+ss.str()); + const Trk::TrackingVolume* caloInNeg = new Trk::TrackingVolume(new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,-0.5*(zup+zlow)))), + cutInBounds->clone(), + cutOutMat[mindex], + dummyLayers, dummyVolumes, + "Calo::GapVolumes::CaloNegativeCutIn"+ss.str()); + // build cutout ( -> MS ) : geometry signature needs to be resolved later : follow naming convention + Trk::CylinderVolumeBounds* cutOutBounds = new Trk::CylinderVolumeBounds( rcut, rout, 0.5*(zup-zlow)); + const Trk::TrackingVolume* caloOutPos = new Trk::TrackingVolume(new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,0.5*(zup+zlow)))), + cutOutBounds, + *m_caloMaterial, + dummyLayers, dummyVolumes, + "Muon::GapVolumes::CaloPositiveCutOut"+ss.str()); + const Trk::TrackingVolume* caloOutNeg = new Trk::TrackingVolume(new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,-0.5*(zup+zlow)))), + cutOutBounds->clone(), + *m_caloMaterial, + dummyLayers, dummyVolumes, + "Muon::GapVolumes::CaloNegativeCutOut"+ss.str()); + + // sign + caloOutPos->sign(Trk::MS); + caloOutNeg->sign(Trk::MS); + + // glue radially and save for final gluing + std::vector<const Trk::TrackingVolume*> cvPos; + cvPos.push_back(cutOutBP.first); + cvPos.push_back(caloInPos); + cvPos.push_back(caloOutPos); + const Trk::TrackingVolume* cutOutPos = m_trackingVolumeCreator->createContainerTrackingVolume(cvPos, + *m_caloMaterial, + "Calo::GapVolumes::CaloPositiveCutoutVolume"+ss.str()); + forwardCutoutVols.push_back(cutOutPos); + // + std::vector<const Trk::TrackingVolume*> cvNeg; + cvNeg.push_back(cutOutBP.second); + cvNeg.push_back(caloInNeg); + cvNeg.push_back(caloOutNeg); + const Trk::TrackingVolume* cutOutNeg = m_trackingVolumeCreator->createContainerTrackingVolume(cvNeg, + *m_caloMaterial, + "Calo::GapVolumes::CaloNegativeCutoutVolume"+ss.str()); + backwardCutoutVols.insert(backwardCutoutVols.begin(),cutOutNeg); + + zlow = zup; + } + } + + ///////////////// + + + if (!centralBuffer) { //(XX) + // all volumes exist : create the super volume at top level + calorimeter = caloCombined; + + } else { //(X) + + std::vector<const Trk::TrackingVolume*> envRVols; + envRVols.push_back(caloCombined); + envRVols.push_back(centralBuffer); + + // add cutouts - final step + if ( forwardCutoutVols.size()>0 || ecNegBuffer ) { + + const Trk::TrackingVolume* caloRVolume = m_trackingVolumeCreator->createContainerTrackingVolume(envRVols, + *m_caloMaterial, + "Calo::Containers::CombinedRCalo"); + std::vector<const Trk::TrackingVolume*> envZVols; + for (unsigned int i=0; i<backwardCutoutVols.size(); i++) envZVols.push_back(backwardCutoutVols[i]); + if (ecNegBuffer) envZVols.push_back(ecNegBuffer); + envZVols.push_back(caloRVolume); + if (ecPosBuffer) envZVols.push_back(ecPosBuffer); + for (unsigned int i=0; i<forwardCutoutVols.size(); i++) envZVols.push_back(forwardCutoutVols[i]); + + calorimeter = m_trackingVolumeCreator->createContainerTrackingVolume(envZVols, + *m_caloMaterial, + m_exitVolume); + + + + } else { // if no cutouts or endcap buffers, this is the top calo volume + + calorimeter = m_trackingVolumeCreator->createContainerTrackingVolume(envRVols, + *m_caloMaterial, + m_exitVolume); + } + + } + + ATH_MSG_VERBOSE( "TrackingVolume 'Calorimeter' built successfully. Wrap it in TrackingGeometry." ); + + delete lArVolumes; lArVolumes = 0; + delete tileVolumes; tileVolumes = 0; + + caloTrackingGeometry = new Trk::TrackingGeometry(calorimeter); + + if (msgLvl(MSG::VERBOSE) && caloTrackingGeometry) + caloTrackingGeometry->printVolumeHierarchy(msg(MSG::VERBOSE)); + + if (m_indexStaticLayers && caloTrackingGeometry) + caloTrackingGeometry->indexStaticLayers( geometrySignature() ); + +// /** enumeration of samplings (i.e.layers) separately for various sub calorimeters */ +// enum CaloSample { +// PreSamplerB=0, EMB1, EMB2, EMB3, // LAr barrel +// PreSamplerE, EME1, EME2, EME3, // LAr EM endcap +// HEC0, HEC1, HEC2, HEC3, // Hadronic end cap cal. +// TileBar0, TileBar1, TileBar2, // Tile barrel +// TileGap1, TileGap2, TileGap3, // Tile gap (ITC & scint) +// TileExt0, TileExt1, TileExt2, // Tile extended barrel +// FCAL0, FCAL1, FCAL2, // Forward EM endcap +// Unknown +// }; + // create dummy infinite IOV Range + // return what you have ... + return std::make_pair(range, caloTrackingGeometry); +} + +void Calo::CaloTrackingGeometryBuilderCond::registerInLayerIndexCaloSampleMap( + Trk::LayerIndexSampleMap& licsMap, + std::vector<CaloCell_ID::CaloSample> ccid, + const Trk::TrackingVolume& vol, + int side) const +{ + + ATH_MSG_VERBOSE( "[+] Registering layers of TrackingVolume '" << vol.volumeName() << "' in LayerIndex/CaloCell_ID map" ); + + // get the confined Layers from the TrackingVolume + const Trk::LayerArray* confinedLayers = vol.confinedLayers(); + if (!confinedLayers) return; + + const std::vector<const Trk::Layer*>& layerObjects = confinedLayers->arrayObjects(); + std::vector<const Trk::Layer*>::const_iterator layerObjIter = layerObjects.begin(); + std::vector<const Trk::Layer*>::const_iterator layerObjEnd = layerObjects.end(); + + // now pick out the material layers (and skip the navigation ones) + std::vector<const Trk::Layer*> materialLayers; + for ( ; layerObjIter != layerObjEnd; ++layerObjIter) + if ((*layerObjIter)->layerMaterialProperties()) materialLayers.push_back((*layerObjIter)); + + unsigned int matLaySize = materialLayers.size(); + unsigned int ccidSize = ccid.size(); + + ATH_MSG_VERBOSE( "[+] Found " << matLaySize << " material layers ( " << ccidSize << " CaloSample ids )" ); + if ( matLaySize != ccidSize ) return; + + // everything's fine for side > 0 + if (side > 0){ + // match 1-to-1 + std::vector<const Trk::Layer*>::iterator layerIt = materialLayers.begin(); + std::vector<const Trk::Layer*>::iterator layerItEnd = materialLayers.end(); + std::vector<CaloCell_ID::CaloSample>::iterator ccidIt = ccid.begin(); + std::vector<CaloCell_ID::CaloSample>::iterator ccidItEnd = ccid.end(); + + for ( ; layerIt != layerItEnd && ccidIt != ccidItEnd; ++layerIt, ++ccidIt) + licsMap.insert(std::make_pair((*layerIt)->layerIndex(),int(*ccidIt))); + + } else { + // the order needs to be reversed, because TG has z-ordering positive defined + + std::vector<CaloCell_ID::CaloSample>::iterator ccidIt = ccid.begin(); + std::vector<CaloCell_ID::CaloSample>::iterator ccidItEnd = ccid.end(); + + for ( ;ccidIt != ccidItEnd; ++ccidIt, --matLaySize) + licsMap.insert(std::make_pair((materialLayers[matLaySize-1])->layerIndex(),int(*ccidIt))); + + } + +} + +std::pair<const Trk::TrackingVolume*,const Trk::TrackingVolume*> Calo::CaloTrackingGeometryBuilderCond::createBeamPipeVolumes(float zmin, float zmax, + std::string name,float& outerRadius ) const +{ + outerRadius = 0.; + + // dummy objects + const Trk::LayerArray* dummyLayers = 0; + const Trk::TrackingVolumeArray* dummyVolumes = 0; + + // beam pipe thickness along the z distance + if (!m_bpCutouts.size()) { + return std::pair<const Trk::TrackingVolume*,const Trk::TrackingVolume*> (0,0); + } + + RZPairVector dim; + dim.push_back(RZPair(m_bpCutouts[0].first,zmin)); + float rOut = m_bpCutouts[0].first; + for (unsigned int i=0; i<m_bpCutouts.size(); i++) { + if (m_bpCutouts[i].second<=dim[0].second) dim[0].first=m_bpCutouts[i].first; + else if ( m_bpCutouts[i].second<=zmax ) dim.push_back(m_bpCutouts[i]); + if ( m_bpCutouts[i].second<=zmax ) rOut = m_bpCutouts[i].first; + } + + if (dim.back().second < zmax) dim.push_back(RZPair(rOut,zmax)); + + if (dim.size()==2) { // simple case + + outerRadius = dim[0].first; + + Trk::CylinderVolumeBounds* bpBounds = new Trk::CylinderVolumeBounds( 0., outerRadius, + 0.5*(zmax-zmin)); + + Amg::Transform3D* bpPos = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,0.5*(zmin+zmax)))); + + const Trk::TrackingVolume* bpVolPos = new Trk::TrackingVolume(bpPos, bpBounds, + *m_caloMaterial, + dummyLayers, dummyVolumes, + "BeamPipe::Positive"+name); + + Amg::Transform3D* bpNeg = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,-0.5*(zmin+zmax)))); + + const Trk::TrackingVolume* bpVolNeg = new Trk::TrackingVolume(bpNeg, bpBounds->clone(), + *m_caloMaterial, + dummyLayers, dummyVolumes, + "BeamPipe::Negative"+name); + + // geometry signature + bpVolPos->sign(Trk::BeamPipe); + bpVolNeg->sign(Trk::BeamPipe); + + return std::pair<const Trk::TrackingVolume*,const Trk::TrackingVolume*> (bpVolPos,bpVolNeg); + + } + + // cutout included + + outerRadius = dim[0].first; + + // find rMax + for (unsigned int i=1; i<dim.size(); i++) if (dim[i].first > outerRadius) outerRadius = dim[i].first; + + // loop over z sections, prepare volumes for gluing + std::vector<const Trk::TrackingVolume*> posVols; + + for (unsigned int i=0; i<dim.size()-1; i++) { + + if (dim[i].second == dim[i+1].second) continue; + + // beam pipe volume + Trk::CylinderVolumeBounds* bpBounds = new Trk::CylinderVolumeBounds( 0., dim[i].first, + 0.5*(dim[i+1].second - dim[i].second)); + + Amg::Transform3D* bpPos = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,0.5*(dim[i+1].second + dim[i].second)))); + + const Trk::TrackingVolume* bpVolPos = new Trk::TrackingVolume(bpPos, bpBounds, + *m_caloMaterial, + dummyLayers, dummyVolumes, + "BeamPipe::Positive"+name); + bpVolPos->sign(Trk::BeamPipe); + + const Trk::TrackingVolume* bpVolGap = 0; + if ( dim[i].first < outerRadius ) { + + Trk::CylinderVolumeBounds* bpGB = new Trk::CylinderVolumeBounds( dim[i].first, outerRadius, + 0.5*(dim[i+1].second - dim[i].second)); + + Amg::Transform3D* bpPB = new Amg::Transform3D(*bpPos); + + bpVolGap = new Trk::TrackingVolume(bpPB, bpGB, + *m_caloMaterial, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::Positive"+name); + } + + const Trk::TrackingVolume* bpSector = bpVolPos; + + if (bpVolGap) { + std::vector<const Trk::TrackingVolume*> gapVols; + gapVols.push_back(bpVolPos); + gapVols.push_back(bpVolGap); + bpSector = m_trackingVolumeCreator->createContainerTrackingVolume(gapVols, + *m_caloMaterial, + "Calo::Container::PositiveBPSector"+name); + } + posVols.push_back(bpSector); + } + + //std::cout <<" processing complex beam pipe sector +: gluing in Z:"<< std::endl; + //for (unsigned int i=0; i<posVols.size(); i++) std::cout <<i<<","<<posVols[i]->volumeName()<<","<<posVols[i]->center().z()<< std::endl; + + const Trk::TrackingVolume* bpPosSector = m_trackingVolumeCreator->createContainerTrackingVolume(posVols, + *m_caloMaterial, + "Calo::Container::PositiveBP"+name); + + //const Trk::CylinderVolumeBounds* testBounds + // = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(bpPosSector->volumeBounds())); + + //if (testBounds) std::cout <<"positive BP sector created at z="<<bpPosSector->center().z()<<" and halfZ="<< testBounds->halflengthZ()<< std::endl; + + + // loop over z sections, prepare volumes for gluing + std::vector<const Trk::TrackingVolume*> negVols; + + for (unsigned int i=0; i<dim.size()-1; i++) { + + float zmax2 = -1.* (dim[i].second); + float zmin2 = -1.* (dim[i+1].second); + + if (zmin2 == zmax2) continue; + + // beam pipe volume + Trk::CylinderVolumeBounds* bpBounds = new Trk::CylinderVolumeBounds( 0., dim[i].first, + 0.5*(zmax2-zmin2)); + + Amg::Transform3D* bpNeg = new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,0.5*(zmin2+zmax2)))); + + const Trk::TrackingVolume* bpVolNeg = new Trk::TrackingVolume(bpNeg, bpBounds, + *m_caloMaterial, + dummyLayers, dummyVolumes, + "BeamPipe::Negative"+name); + bpVolNeg->sign(Trk::BeamPipe); + + const Trk::TrackingVolume* bpVolGap = dim[i].first < outerRadius ? + new Trk::TrackingVolume(new Amg::Transform3D(*bpNeg), + new Trk::CylinderVolumeBounds( dim[i].first, outerRadius, + 0.5*(zmax2 - zmin2)), + *m_caloMaterial, + dummyLayers, dummyVolumes, + "Calo::GapVolumes::Negative"+name) : 0 ; + + const Trk::TrackingVolume* bpSector = bpVolNeg; + + if (bpVolGap) { + std::vector<const Trk::TrackingVolume*> gapVols; + gapVols.push_back(bpVolNeg); + gapVols.push_back(bpVolGap); + bpSector = m_trackingVolumeCreator->createContainerTrackingVolume(gapVols, + *m_caloMaterial, + "Calo::Container::NegativeBPSector"+name); + } + + if (!negVols.size()) negVols.push_back(bpSector); + else negVols.insert(negVols.begin(),bpSector); + } + + //std::cout <<" processing complex beam pipe sector -: gluing in Z:"<< std::endl; + //for (unsigned int i=0; i<negVols.size(); i++) std::cout <<i<<","<<negVols[i]->volumeName()<<","<<negVols[i]->center().z()<< std::endl; + + const Trk::TrackingVolume* bpNegSector = m_trackingVolumeCreator->createContainerTrackingVolume(negVols, + *m_caloMaterial, + "Calo::Container::NegativeBP"+name); + + //testBounds + // = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(bpNegSector->volumeBounds())); + + //if (testBounds) std::cout <<"negative BP sector created at z="<<bpNegSector->center().z()<<" and halfZ="<< testBounds->halflengthZ()<< std::endl; + + return std::pair<const Trk::TrackingVolume*,const Trk::TrackingVolume*> (bpPosSector,bpNegSector); + +} + + + diff --git a/Calorimeter/CaloTrackingGeometry/src/components/CaloTrackingGeometry_entries.cxx b/Calorimeter/CaloTrackingGeometry/src/components/CaloTrackingGeometry_entries.cxx index b3f13e36bc0..ea238193ceb 100644 --- a/Calorimeter/CaloTrackingGeometry/src/components/CaloTrackingGeometry_entries.cxx +++ b/Calorimeter/CaloTrackingGeometry/src/components/CaloTrackingGeometry_entries.cxx @@ -2,9 +2,12 @@ #include "CaloTrackingGeometry/CaloSurfaceBuilder.h" #include "CaloTrackingGeometry/CaloSurfaceHelper.h" +#include "CaloTrackingGeometry/CaloTrackingGeometryBuilderCond.h" + using namespace Calo; DECLARE_COMPONENT( CaloTrackingGeometryBuilder ) DECLARE_COMPONENT( CaloSurfaceBuilder ) DECLARE_COMPONENT( CaloSurfaceHelper ) +DECLARE_COMPONENT( CaloTrackingGeometryBuilderCond ) diff --git a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/BeamPipeBuilderCond.h b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/BeamPipeBuilderCond.h new file mode 100755 index 00000000000..9f4dc6b7b77 --- /dev/null +++ b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/BeamPipeBuilderCond.h @@ -0,0 +1,119 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// BeamPipeBuilderCond.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef INDETTRACKINGGEOMETRY_BEAMPIPEBUILDERCOND_H +#define INDETTRACKINGGEOMETRY_BEAMPIPEBUILDERCOND_H + +// Athena +#include "AthenaBaseComps/AthAlgTool.h" +// Trk +#include "TrkDetDescrInterfaces/ILayerBuilderCond.h" +// STL +#include <vector> +#include <utility> + +namespace Trk { + class CylinderLayer; + class DiscLayer; + class PlaneLayer; +} + +class BeamPipeDetectorManager; + +namespace InDet { + + /** @class BeamPipeBuilderCond + Simple LayerBuilder for the BeamPipe, + can be configured through jobOptions: + - radius + - halflength + - thickness + - MaterialProperties + + later on the slight shift/rotation of the BeamPipe can be implemented + - make a binding to the database afterwards + + @author Andreas.Salzburger@cern.ch + */ + class BeamPipeBuilderCond : public AthAlgTool, + virtual public Trk::ILayerBuilderCond { + + + public: + /** AlgTool style constructor */ + BeamPipeBuilderCond(const std::string&,const std::string&,const IInterface*); + /** Destructor */ + virtual ~BeamPipeBuilderCond(); + + /** AlgTool initialize method */ + StatusCode initialize(); + /** AlgTool finalize method */ + StatusCode finalize(); + + /** LayerBuilder interface method - returning Barrel-like layers */ + std::pair<EventIDRange, const std::vector< const Trk::CylinderLayer* >* > cylindricalLayers(const EventContext& ctx) const; + + /** LayerBuilder interface method - returning Endcap-like layers */ + std::pair<EventIDRange, const std::vector< const Trk::DiscLayer* >* > discLayers(const EventContext& ctx) const; + + /** LayerBuilder interface method - returning Planar-like layers */ + std::pair<EventIDRange, const std::vector< const Trk::PlaneLayer* >* > planarLayers(const EventContext& ctx) const; + + /** Name identification */ + const std::string& identification() const; + + private: + + bool m_beamPipeFromDb; //!< steer beam pipe parameters from DataBase + const BeamPipeDetectorManager* m_beamPipeMgr; //!< the beam pipe manager + std::string m_beamPipeMgrName; //!< the name of the beam pipe manager to be configured + double m_beamPipeEnvelope; //!< radial envelope when taking the Top volume radius + + double m_beamPipeOffsetX; //!< beam pipe offset in x + double m_beamPipeOffsetY; //!< beam pipe offset in y + double m_beamPipeRadius; //!< radius of the beam pipe + double m_beamPipeHalflength; //!< halflength of the beampipe + double m_beamPipeThickness; //!< thickness of the beam pipe + double m_beamPipeX0; //!< X0 of the beam pipe + double m_beamPipeL0; //!< X0 of the beam pipe + //double m_beamPipedEdX; //!< dEdX of the beam pipe + double m_beamPipeA; //!< averageA of the beam pipe + double m_beamPipeZ; //!< averageZ of the beam pipe + double m_beamPipeRho; //!< averageRho of the beam pipe + + unsigned int m_beamPipeBinsZ; //!< number of bins in the beam pipe + + std::string m_identification; //!< string identification + + + }; + + inline std::pair<EventIDRange, const std::vector< const Trk::DiscLayer* >* > BeamPipeBuilderCond::discLayers(const EventContext&) const + { + //create dummy infinite range + EventIDRange range; + return std::pair<EventIDRange, const std::vector< const Trk::DiscLayer* >* >(range,0); + } + + inline std::pair<EventIDRange, const std::vector< const Trk::PlaneLayer* >* > BeamPipeBuilderCond::planarLayers(const EventContext&) const + { + //create dummy infinite range + EventIDRange range; + return std::pair<EventIDRange, const std::vector< const Trk::PlaneLayer* >* >(range, 0); + } + + inline const std::string& BeamPipeBuilderCond::identification() const + { return m_identification; } + + +} // end of namespace + + +#endif // INDETTRACKINGGEOMETRY_BEAMPIPEBUILDERCOND_H + + diff --git a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/RobustTrackingGeometryBuilderCond.h b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/RobustTrackingGeometryBuilderCond.h new file mode 100755 index 00000000000..e92774b734c --- /dev/null +++ b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/RobustTrackingGeometryBuilderCond.h @@ -0,0 +1,138 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// RobustTrackingGeometryBuilderCond.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef INDETTRACKINGGEOMETRY_ROBUSTTRACKINGGEOMETRYBUILDERCOND_H +#define INDETTRACKINGGEOMETRY_ROBUSTTRACKINGGEOMETRYBUILDERCOND_H + +//Trk +#include "TrkDetDescrInterfaces/IGeometryBuilderCond.h" +#include "TrkDetDescrUtils/BinningType.h" +#include "TrkGeometry/TrackingVolumeManipulator.h" +// Gaudi +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/ToolHandle.h" +#include "GaudiKernel/ServiceHandle.h" +// STL +#include <vector> +#include <string> + +#ifndef TRKDETDESCR_TAKESMALLERBIGGER +#define TRKDETDESCR_TAKESMALLERBIGGER +#define takeSmaller(current,test) current = current < test ? current : test +#define takeBigger(current,test) current = current > test ? current : test +#define takeSmallerBigger(cSmallest, cBiggest, test) takeSamller(cSmallest, cBiggest, test); takeBigger(cSmallest, cBiggest,test) +#endif + + +namespace Trk { + class TrackingGeometry; + class ILayerBuilderCond; + class ITrackingVolumeCreator; + class ILayerArrayCreator; + class IMagneticFieldTool; + class Layer; + class Material; + class MagneticFieldProperties; +} + +class IEnvelopeDefSvc; + +namespace InDet { + + + /** @class RobustTrackingGeometryBuilderCond + + New Geometry builder that adapts to different layer setups + + Only a few parameters are not automated: + - m_outwardsFraction: this defines how much you orient yourself on the next bigger layer + if you wrap an outer volume around an inner 0.5 would lead to a boundary fully in bewteen + 1. at the outer boundary, 0. at the inner boundary + + @author Andreas.Salzburger@cern.ch + + */ + + class RobustTrackingGeometryBuilderCond : public AthAlgTool, + public Trk::TrackingVolumeManipulator, + virtual public Trk::IGeometryBuilderCond { + + + public: + /** Constructor */ + RobustTrackingGeometryBuilderCond(const std::string&,const std::string&,const IInterface*); + + /** Destructor */ + virtual ~RobustTrackingGeometryBuilderCond(); + + /** AlgTool initailize method.*/ + StatusCode initialize(); + /** AlgTool finalize method */ + StatusCode finalize(); + /** TrackingGeometry Interface methode */ + std::pair<EventIDRange, const Trk::TrackingGeometry*> trackingGeometry(const EventContext& ctx, std::pair<EventIDRange, const Trk::TrackingVolume*> tVolPair) const; + + /** The unique signature */ + Trk::GeometrySignature geometrySignature() const { return Trk::ID; } + + private: + + /** Private method, creates and packs a triple containing of NegEndcap-Barrel-PosEndcap layers */ + const Trk::TrackingVolume* packVolumeTriple(const std::vector<const Trk::Layer*>& negLayers, + const std::vector<const Trk::Layer*>& centralLayers, + const std::vector<const Trk::Layer*>& posLayers, + double rMin, double rMax, + double zMin, double zPosCentral, + const std::string& baseName="UndefinedVolume", + int colorCode = 21, + Trk::BinningType bintype=Trk::arbitrary) const; + + /** Private method, creates and packs a triple containing of NegEndcap-Barrel-PosEndcap volumes */ + const Trk::TrackingVolume* packVolumeTriple(const std::vector<const Trk::TrackingVolume*>& negVolumes, + const std::vector<const Trk::TrackingVolume*>& centralVolumes, + const std::vector<const Trk::TrackingVolume*>& posVolumes, + const std::string& baseName="UndefinedVolume") const; + + // helper tools for the geometry building + ToolHandle<Trk::ILayerBuilderCond> m_beamPipeBuilder; //!< BeamPipe builder (is different from layers) + ToolHandleArray<Trk::ILayerBuilderCond> m_layerBuilders; //!< Helper Tools for the Layer creation + ToolHandle<Trk::ITrackingVolumeCreator> m_trackingVolumeCreator; //!< Helper Tool to create TrackingVolumes + ToolHandle<Trk::ILayerArrayCreator> m_layerArrayCreator; //!< Helper Tool to create BinnedArrays + + // configurations for the layer builders + std::vector<int> m_layerBinningType; //!< binning type for the provided layers + std::vector<int> m_colorCodesConfig; //!< Color codes + + // enclosing endcap/cylinder layer + ServiceHandle<IEnvelopeDefSvc> m_enclosingEnvelopeSvc; //!< the service to provide the ID envelope size + std::vector<double> m_enclosingCylinderRadius; //!< the cylinder layer inside the enclosing volume + std::vector<double> m_enclosingDiscPositionZ; //!< the disc position inside the enclosing volume + + double m_layerEnvelopeCover; //!< innermost - outermost + bool m_buildBoundaryLayers; //!< create boundary layers + bool m_replaceJointBoundaries; //!< run with replacement of all joint boundaries + + // magnetic & material field configuration + mutable Trk::Material* m_materialProperties; //!< overal material properties of the ID + mutable Trk::MagneticFieldProperties* m_magneticFieldProperties; //!< overal mag field properties of the ID + // outer envelope + double m_outwardsFraction; //!< defines how much you orient yourself in an outwards way (see above) + // robust layer indexing + bool m_indexStaticLayers; //!< forces robust indexing for layers + // naming schema + std::string m_namespace; //!< identificaton namespace + // ID container + std::string m_exitVolume; //!< the final ID container + bool m_isSLHC; //!< changes volume boundary calculation for SLHC layouts + }; + +} // end of namespace + +#endif //INDETTRACKINGGEOMETRY_ROBUSTTRACKINGGEOMETRYBUILDERCOND_H + + diff --git a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/SiLayerBuilderCond.h b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/SiLayerBuilderCond.h new file mode 100755 index 00000000000..62869355d35 --- /dev/null +++ b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/SiLayerBuilderCond.h @@ -0,0 +1,162 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// SiLayerBuilderCond.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef INDETTRACKINGGEOMETRY_SILAYERBUILDERNCOND_H +#define INDETTRACKINGGEOMETRY_SILAYERBUILDERNCOND_H + +// Athena +#include "AthenaBaseComps/AthAlgTool.h" +// Amg +#include "GeoPrimitives/GeoPrimitives.h" +// Trk +#include "TrkDetDescrInterfaces/ILayerBuilderCond.h" +#include "TrkDetDescrUtils/SharedObject.h" +// STL +#include <vector> +#include <utility> //for std::pair + +#include "InDetReadoutGeometry/SiDetectorElementCollection.h" + +class PixelID; +class SCT_ID; + +#ifndef TRKDETDESCR_TAKESMALLERBIGGER +#define TRKDETDESCR_TAKESMALLERBIGGER +#define takeSmaller(current,test) current = current < test ? current : test +#define takeBigger(current,test) current = current > test ? current : test +#define takeSmallerBigger(cSmallest, cBiggest, test) takeSmaller(cSmallest, test); takeBigger(cBiggest, test) +#endif + +namespace InDetDD { + class SiDetectorManager; +} + +namespace Trk { + class Surface; + class CylinderLayer; + class DiscLayer; + class PlaneLayer; + class LayerMaterialProperties; + typedef std::pair< SharedObject<const Surface>, Amg::Vector3D > SurfaceOrderPosition; +} + +namespace InDet { + + /** @class SiLayerBuilderCond + + The SiLayerBuilderCond parses the senstive detector elments and orders them onto a + Layer surface. + + It also uses the SiNumerology to construct the BinUtility and then orders the representing + detector surfaces on the layers. + + It performs an automated detector if an equidistant or non-equidistant binning + is to be used for the barrel case. + + There is an option to run in split mode for multiple pixel systems of different + layer / endcap dimensions. In such a case, a cache is filled at the first time + running for the pixel system of greater dimensions and just return in the second pass. + + @author Andreas.Salzburger@cern.ch + */ + class SiLayerBuilderCond : public AthAlgTool, virtual public Trk::ILayerBuilderCond { + + public: + + /** AlgTool style constructor */ + SiLayerBuilderCond(const std::string&,const std::string&,const IInterface*); + + /** Destructor */ + virtual ~SiLayerBuilderCond(); + + /** AlgTool initialize method */ + StatusCode initialize(); + /** AlgTool finalize method */ + StatusCode finalize(); + + /** LayerBuilder interface method - returning Barrel-like layers */ + std::pair<EventIDRange, const std::vector< const Trk::CylinderLayer* >* > cylindricalLayers(const EventContext& ctx) const; + + /** LayerBuilder interface method - returning Endcap-like layers */ + std::pair<EventIDRange, const std::vector< const Trk::DiscLayer* >* > discLayers(const EventContext& ctx) const; + + /** LayerBuilder interface method - returning Planar-like layers */ + std::pair<EventIDRange, const std::vector< const Trk::PlaneLayer* >* > planarLayers(const EventContext& ctx) const; + + /** Name identification */ + const std::string& identification() const; + + private: + std::vector< const Trk::CylinderLayer* >* dressCylinderLayers(const std::vector< const Trk::CylinderLayer* >& dLayers) const; + + /** create the disc layers, if no vector is given, then it's the first pass, else it's the DBM for the Pixels */ + std::pair<EventIDRange, std::vector< const Trk::DiscLayer* >* > createDiscLayers(const EventContext& ctx, std::vector<const Trk::DiscLayer* >* dLayers = nullptr) const; + + const Trk::LayerMaterialProperties* barrelLayerMaterial(double r, double hz) const; //!< helper method to construct barrel material + const Trk::LayerMaterialProperties* endcapLayerMaterial(double rMin, double rMax) const; //!< helper method to construct endcap material + + void registerSurfacesToLayer(const std::vector<const Trk::Surface*>& surfaces, const Trk::Layer& layer) const; //!< layer association + + bool m_pixelCase; //!< flag for pixel/sct + + const InDetDD::SiDetectorManager* m_siMgr; //!< the Si Detector Manager + std::string m_siMgrLocation; //!< the location of the Pixel Manager + const PixelID* m_pixIdHelper; //!< pixel Id Helper + const SCT_ID* m_sctIdHelper; //!< sct Id Helper + + bool m_setLayerAssociation; //!< Set Layer Association + + // barrel layer section + std::vector<double> m_barrelAdditionalLayerR; //!< Create an additional layer at these radii + std::vector<int> m_barrelAdditionalLayerType; //!< material layer 1 - navigation layer 0 + size_t m_barrelLayerBinsZ; //!< Barrel bins for the material in z + size_t m_barrelLayerBinsPhi; //!< Barrel bins for the material in phi + double m_barrelEnvelope; //!< envelope around rMin/rMax + double m_barrelEdbTolerance; //!< tolerance in percent how much the bin sizes can change + + bool m_endcapRingLayout; //!< will not synchronise the rMin/rMax + std::vector<double> m_endcapAdditionalLayerPosZ; //!< Create additional endcaps at these z positions + std::vector<int> m_endcapAdditionalLayerType; //!< material layer 1 - navigation layer 0 ( for volume adjustment ) + size_t m_endcapLayerBinsR; //!< Barrel bins for the material in r + size_t m_endcapLayerBinsPhi; //!< Barrel bins for the material in phi + double m_endcapEnvelope; //!< envelope around rMin/rMax + bool m_endcapComplexRingBinning; //!< make std::vector<R> rings, could be different for layers + + std::string m_identification; //!< string identification + + int m_splitMode; //!< Check for the split mode : -1 | 0 | 1 + double m_splitTolerance; //!< difference in layer half length to provoke the split + + static double s_splitRadius; //!< Split radius for multiple pixel systems + static std::vector<const Trk::CylinderLayer*> s_splitCylinderLayers; //!< cached SLHC/split cylinder layers for projective layout + static std::vector<const Trk::DiscLayer*> s_splitDiscLayers; //!< cached SLHC/split disc layers for projective layout + static EventIDRange s_splitIOVRange; //!< store range of splitLayers + + bool m_runGeometryValidation; //!< run the validation of the geometry ( no empty bins) + SG::ReadCondHandleKey<InDetDD::SiDetectorElementCollection> m_SCT_ReadKey{this, "SCT_ReadKey", "SCT_DetectorElementCollection", "Key of output SiDetectorElementCollection for SCT"}; + SG::ReadCondHandleKey<InDetDD::SiDetectorElementCollection> m_PixelReadKey{this, "PixelReadKey", "PixelDetectorElementCollection", "Key of output SiDetectorElementCollection for Pixel"}; + + + }; + + inline std::pair<EventIDRange, const std::vector< const Trk::PlaneLayer* >* > SiLayerBuilderCond::planarLayers(const EventContext&) const + { + //create dummy infinite range + EventIDRange range; + return std::pair<EventIDRange, const std::vector< const Trk::PlaneLayer* >* >(range, 0); + } + + inline const std::string& SiLayerBuilderCond::identification() const + { return m_identification; } + +} // end of namespace + + +#endif // INDETTRACKINGGEOMETRY_SILAYERBUILDERNCOND_H + + diff --git a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/StagedTrackingGeometryBuilderCond.h b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/StagedTrackingGeometryBuilderCond.h new file mode 100755 index 00000000000..7eeddeb3a88 --- /dev/null +++ b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/StagedTrackingGeometryBuilderCond.h @@ -0,0 +1,255 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// StagedTrackingGeometryBuilderCond.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef INDETTRACKINGGEOMETRY_STAGEDTRACKINGGEOMETRYBUILDERCOND_H +#define INDETTRACKINGGEOMETRY_STAGEDTRACKINGGEOMETRYBUILDERCOND_H + +//Trk +#include "TrkDetDescrInterfaces/IGeometryBuilderCond.h" +#include "TrkDetDescrUtils/BinningType.h" +#include "TrkGeometry/TrackingVolumeManipulator.h" +//InDet +#include "StagedTrackingGeometryBuilder.h" +// Gaudi +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/ToolHandle.h" +#include "GaudiKernel/ServiceHandle.h" +// STL +#include <vector> +#include <string> + +#ifndef TRKDETDESCR_TAKESMALLERBIGGER +#define TRKDETDESCR_TAKESMALLERBIGGER +#define takeSmaller(current,test) current = current < test ? current : test +#define takeBigger(current,test) current = current > test ? current : test +#define takeSmallerBigger(cSmallest, cBiggest, test) takeSmaller(cSmallest, test); takeBigger(cBiggest, test) +#endif + + +namespace Trk { + class TrackingGeometry; + class ILayerProviderCond; + class ITrackingVolumeCreator; + class ILayerArrayCreator; + class IMagneticFieldTool; + class Layer; + class Material; + class MagneticFieldProperties; +} + +class IEnvelopeDefSvc; + +namespace InDet { + + /** @struct LayerSetup + - helps understanding how to pack the layers into a volume compound + */ +// implemented in StagedTrackingGeometrybuilder.h (without "Cond") +// struct LayerSetup { +// +// // the layer cache +// std::vector<const Trk::Layer*> negativeLayers; +// std::vector<const Trk::Layer*> centralLayers; +// std::vector<const Trk::Layer*> positiveLayers; +// +// // center information +// double minRadiusCenter; +// double maxRadiusCenter; +// double zExtendCenter; +// int binningCenter; +// +// // endcap information +// bool buildEndcap; +// double minRadiusEndcap; +// double maxRadiusEndcap; +// double minZextendEndcap; +// double maxZextendEndcap; +// int binningEndcap; +// +// // full setup information +// double zSector; +// double rMin; +// double rMax; +// double zMax; +// +// std::string identification; +// int colorCode; +// +// LayerSetup(const std::string& idName, +// int cCode, +// const std::vector<const Trk::Layer*>& negLayers, +// const std::vector<const Trk::Layer*>& cenLayers, +// const std::vector<const Trk::Layer*>& posLayers, +// double minRc, double maxRc, double zC, int binC, +// bool bec=false, double minRe=0., double maxRe=0., double zMinE=0., double zMaxE=0., int binE = 0) : +// negativeLayers(negLayers), +// centralLayers(cenLayers), +// positiveLayers(posLayers), +// minRadiusCenter(minRc), +// maxRadiusCenter(maxRc), +// zExtendCenter(zC), +// binningCenter(binC), +// buildEndcap(bec), +// minRadiusEndcap(minRe), +// maxRadiusEndcap(maxRe), +// minZextendEndcap(zMinE), +// maxZextendEndcap(zMaxE), +// binningEndcap(binE), +// identification(idName), +// colorCode(cCode) +// { +// rMin = minRadiusCenter < minRadiusEndcap ? minRadiusCenter : minRadiusEndcap; +// rMax = maxRadiusCenter > maxRadiusEndcap ? maxRadiusCenter : maxRadiusEndcap; +// zMax = zExtendCenter > maxZextendEndcap ? zExtendCenter : maxZextendEndcap; +// zSector = buildEndcap ? 0.5*(zExtendCenter+minZextendEndcap) : zExtendCenter; +// +// } +// +// }; + + + /** @class StagedTrackingGeometryBuilderCond + + New Geometry builder that adapts to different layer setups + + Only a few parameters are not automated: + - m_outwardsFraction: this defines how much you orient yourself on the next bigger layer + if you wrap an outer volume around an inner 0.5 would lead to a boundary fully in bewteen + 1. at the outer boundary, 0. at the inner boundary + + @author Andreas.Salzburger@cern.ch + + */ + + class StagedTrackingGeometryBuilderCond : public AthAlgTool, + public Trk::TrackingVolumeManipulator, + virtual public Trk::IGeometryBuilderCond { + + + public: + /** Constructor */ + StagedTrackingGeometryBuilderCond(const std::string&,const std::string&,const IInterface*); + + /** Destructor */ + virtual ~StagedTrackingGeometryBuilderCond(); + + /** AlgTool initailize method.*/ + StatusCode initialize(); + /** AlgTool finalize method */ + StatusCode finalize(); + /** TrackingGeometry Interface methode */ + std::pair<EventIDRange, const Trk::TrackingGeometry*> trackingGeometry(const EventContext& ctx, std::pair<EventIDRange, const Trk::TrackingVolume*> tVolPair) const; + + /** The unique signature */ + Trk::GeometrySignature geometrySignature() const { return Trk::ID; } + + private: + /** Private helper method, estimates the overal dimensions */ + LayerSetup estimateLayerSetup(const std::string& idName, size_t ils, + const std::vector<const Trk::Layer*>& negLayers, + const std::vector<const Trk::Layer*>& centralLayers, + const std::vector<const Trk::Layer*>& posLayers, + double maxR, double maxZ) const; + + /** Private helper method to estimate the layer dimensions */ + void estimateLayerDimensions(const std::vector<const Trk::Layer*>& layers, + double& rMin, double& rMax, double& zMin, double& zMax) const; + + /** Private helper method to check if a sector is compatible with the cache */ + bool setupFitsCache(LayerSetup& layerSetup, std::vector<InDet::LayerSetup>& layerSetupCache) const; + + + /** Private helper method to flush the cache into the id volumes - return volume is the one to be provided */ + const Trk::TrackingVolume* createFlushVolume(std::vector<InDet::LayerSetup>& layerSetupCache, + double innerRadius, double& outerRadius, double extendZ) const; + + /** Private helper method, creates a TrackingVolume - and checks if configured - for Ring Layout + - in case a ring layout is given, it creates the corresponding sub-volumes and updates the radius + */ + const Trk::TrackingVolume* createTrackingVolume(const std::vector<const Trk::Layer*>& layers, + double innerRadius, double& outerRadius, + double zMin, double zMax, + const std::string& volumeName, + Trk::BinningType btype, + bool doAdjustOuterRadius = true) const; + + /** Private helper method, creates and packs a triple containing of NegEndcap-Barrel-PosEndcap layers + - in case of a ring layout the subvolumes are created and the rMax is adapted + */ + const Trk::TrackingVolume* packVolumeTriple(const LayerSetup& layerSetup, + double rMin, double& rMax, + double zMin, double zPosCentral) const; + + /** Private helper method, creates and packs a triple containing of NegEndcap-Barrel-PosEndcap volumes */ + const Trk::TrackingVolume* packVolumeTriple(const std::vector<const Trk::TrackingVolume*>& negVolumes, + const std::vector<const Trk::TrackingVolume*>& centralVolumes, + const std::vector<const Trk::TrackingVolume*>& posVolumes, + const std::string& baseName="UndefinedVolume") const; + + /** Private helper method for detection of Ring layout */ + bool ringLayout(const std::vector<const Trk::Layer*>& layers, std::vector<double>& rmins, std::vector<double>& rmaxs) const; + + /** helper method needed for the Ring layout */ + void checkForInsert(std::vector<double>& radii, double radius) const; + + // helper tools for the geometry building + ToolHandleArray<Trk::ILayerProviderCond> m_layerProviders; //!< Helper Tools for the Layer creation, includes beam pipe builder + ToolHandle<Trk::ITrackingVolumeCreator> m_trackingVolumeCreator; //!< Helper Tool to create TrackingVolumes + ToolHandle<Trk::ILayerArrayCreator> m_layerArrayCreator; //!< Helper Tool to create BinnedArrays + + // configurations for the layer builders + std::vector<int> m_layerBinningTypeCenter; //!< binning type for the provided layers + std::vector<int> m_layerBinningTypeEndcap; //!< binning type for the provided layers + std::vector<int> m_colorCodesConfig; //!< Color codes + + // enclosing endcap/cylinder layer + ServiceHandle<IEnvelopeDefSvc> m_enclosingEnvelopeSvc; //!< the service to provide the ID envelope size + std::vector<double> m_enclosingCylinderRadius; //!< the cylinder layer inside the enclosing volume + std::vector<double> m_enclosingDiscPositionZ; //!< the disc position inside the enclosing volume + + double m_layerEnvelopeCover; //!< innermost - outermost + bool m_buildBoundaryLayers; //!< create boundary layers + bool m_replaceJointBoundaries; //!< run with replacement of all joint boundaries + + // magnetic & material field configuration + mutable Trk::Material* m_materialProperties; //!< overal material properties of the ID + mutable Trk::MagneticFieldProperties* m_magneticFieldProperties; //!< overal mag field properties of the ID + + // robust layer indexing + bool m_indexStaticLayers; //!< forces robust indexing for layers + + // check for endcap ring layout + bool m_checkForRingLayout; //!< this is to check for the endcap ring layout + double m_ringTolerance; //!< the ring tolerance + + // naming schema + std::string m_namespace; //!< identificaton namespace + // ID container + std::string m_exitVolume; //!< the final ID container + }; + + inline void StagedTrackingGeometryBuilderCond::checkForInsert(std::vector<double>& radii, double radius) const { + bool exists = false; + // loop and check + for (auto& checkr : radii) { + if ( (checkr-radius)*(checkr-radius) < m_ringTolerance*m_ringTolerance ){ + exists = true; break; + } + } + // insert + if (!exists) radii.push_back(radius); + // re-sort + std::sort(radii.begin(),radii.end()); + } + + +} // end of namespace + +#endif //INDETTRACKINGGEOMETRY_STAGEDTRACKINGGEOMETRYBUILDERCOND_H + + diff --git a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/TRT_LayerBuilderCond.h b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/TRT_LayerBuilderCond.h new file mode 100755 index 00000000000..19a6395a072 --- /dev/null +++ b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/InDetTrackingGeometry/TRT_LayerBuilderCond.h @@ -0,0 +1,117 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// TRT_LayerBuilderCond.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef INDETTRACKINGGEOMETRY_TRT_LAYERBUILDERCOND_H +#define INDETTRACKINGGEOMETRY_TRT_LAYERBUILDERCOND_H + +// Amg +#include "GeoPrimitives/GeoPrimitives.h" +// Athena +#include "AthenaBaseComps/AthAlgTool.h" +// Trk +#include "TrkDetDescrInterfaces/ILayerBuilderCond.h" +#include "TrkDetDescrUtils/SharedObject.h" +// STL +#include <vector> + +#ifndef TRKDETDESCR_TAKESMALLERBIGGER +#define TRKDETDESCR_TAKESMALLERBIGGER +#define takeSmaller(current,test) current = current < test ? current : test +#define takeBigger(current,test) current = current > test ? current : test +#define takeSmallerBigger(cSmallest, cBiggest, test) takeSmaller(cSmallest, test); takeBigger(cBiggest, test) +#endif + +namespace InDetDD { + class TRT_DetectorManager; +} + +namespace Trk { + class Surface; + class Layer; + class CylinderLayer; + class DiscLayer; + class ExtendedMaterialProperties; + typedef std::pair< SharedObject<const Surface>, Amg::Vector3D > SurfaceOrderPosition; +} + +namespace InDet { + + /** @class TRT_LayerBuilderCond + + @author Andreas.Salzburger@cern.ch + */ + class TRT_LayerBuilderCond : public AthAlgTool, + virtual public Trk::ILayerBuilderCond { + + /** Declare the TRT_VolumeBuilder as friend */ + friend class TRT_VolumeBuilder; + + public: + + /** AlgTool style constructor */ + TRT_LayerBuilderCond(const std::string&,const std::string&,const IInterface*); + /** Destructor */ + virtual ~TRT_LayerBuilderCond(); + + /** AlgTool initialize method */ + StatusCode initialize(); + /** AlgTool finalize method */ + StatusCode finalize(); + + /** LayerBuilderCond interface method - returning Barrel-like layers */ + std::pair<EventIDRange, const std::vector< const Trk::CylinderLayer* >* > cylindricalLayers(const EventContext& ctx) const; + + /** LayerBuilderCond interface method - returning Endcap-like layers */ + std::pair<EventIDRange, const std::vector< const Trk::DiscLayer* >* > discLayers(const EventContext& ctx) const; + + /** LayerBuilderCond interface method - returning Planar-like layers */ + std::pair<EventIDRange, const std::vector< const Trk::PlaneLayer* >* > planarLayers(const EventContext& ctx) const; + + /** Name identification */ + const std::string& identification() const; + + private: + const InDetDD::TRT_DetectorManager* m_trtMgr; //!< the TRT Manager + std::string m_trtMgrLocation; //!< the location of the TRT Manager + + double m_layerStrawRadius; //!< straw radius + double m_layerThickness; //!< modelled layer thickness + bool m_modelGeometry; //!< Build the geometry with model layers + unsigned int m_modelBarrelLayers; //!< model barrel layers with material + unsigned int m_modelEndcapLayers; //!< model endcap layers with material + + unsigned int m_barrelLayerBinsZ; //!< Bins for the Barrel material - in z + unsigned int m_barrelLayerBinsPhi; //!< Bins for the Barrel material - in phi + unsigned int m_endcapLayerBinsR; //!< Bins for the Endcap material - in r + unsigned int m_endcapLayerBinsPhi; //!< Bins for the Endcap material - in phi + bool m_endcapConly; //!< Only build the endcapC + + bool m_registerStraws; //!< register the straws + int m_barrelSectorAtPiBoundary; //!< this is the barrel Sector where +pi/-pi is within + + std::string m_identification; //!< string identification + + + }; + + inline std::pair<EventIDRange, const std::vector< const Trk::PlaneLayer* >* > TRT_LayerBuilderCond::planarLayers(const EventContext&) const + { + //create dummy infinite range + EventIDRange range; + return std::pair<EventIDRange, const std::vector< const Trk::PlaneLayer* >* >(range, 0); + } + + inline const std::string& TRT_LayerBuilderCond::identification() const + { return m_identification; } + +} // end of namespace + + +#endif // INDETTRACKINGGEOMETRY_TRT_LAYERBUILDERCOND_H + + diff --git a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/python/ConfiguredInDetTrackingGeometryBuilderCond.py b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/python/ConfiguredInDetTrackingGeometryBuilderCond.py new file mode 100644 index 00000000000..f592e04e99d --- /dev/null +++ b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/python/ConfiguredInDetTrackingGeometryBuilderCond.py @@ -0,0 +1,201 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + +###################################################### +# ConfiguredInDetTrackingGeometry module +# +# it inherits from RobustTrackingGeometryBuilderConf and performs +# standard configuration +# +###################################################### + +# import the Extrapolator configurable +from InDetTrackingGeometry.InDetTrackingGeometryConf import InDet__RobustTrackingGeometryBuilderCond +from AthenaCommon.DetFlags import DetFlags + +# define the class +class ConfiguredInDetTrackingGeometryBuilderCond( InDet__RobustTrackingGeometryBuilderCond ): + # constructor + def __init__(self,name = 'InDetTrackingGeometryBuilderCond', + namePrefix = '', + setLayerAssociation = True, + buildTrtStrawLayers = False): + + # get the ToolSvc + from AthenaCommon.AppMgr import ToolSvc, ServiceMgr + + # the Detector flags to be imported + from TrkDetDescrSvc.TrkDetDescrJobProperties import TrkDetFlags + + # beampipe + from InDetTrackingGeometry.InDetTrackingGeometryConf import InDet__BeamPipeBuilderCond + BeamPipeBuilder = InDet__BeamPipeBuilderCond(name=namePrefix+'BeamPipeBuilderCond') + BeamPipeBuilder.BeamPipeRadius = TrkDetFlags.BeamPipeRadius() + BeamPipeBuilder.BeamPipeThickness = TrkDetFlags.BeamPipeThickness() + BeamPipeBuilder.BeamPipeMaterialBinsZ = TrkDetFlags.BeamPipeLayerMaterialBinsZ() + BeamPipeBuilder.OutputLevel = TrkDetFlags.InDetBuildingOutputLevel() + ToolSvc += BeamPipeBuilder + + # the layer builders + layerbuilders = [] + binnings = [] + colors = [] + + # @TODO put DetFlags isOn here, but make sure that this is really when the detector is not built + + # PIXEL building + if DetFlags.pixel_on(): + from InDetTrackingGeometry.InDetTrackingGeometryConf import InDet__SiLayerBuilderCond + PixelLayerBuilder = InDet__SiLayerBuilderCond(name=namePrefix+'PixelLayerBuilderCond') + PixelLayerBuilder.PixelCase = True + PixelLayerBuilder.Identification = 'Pixel' + PixelLayerBuilder.SiDetManagerLocation = 'Pixel' + # additionall layers - handle with care ! + PixelLayerBuilder.BarrelAdditionalLayerRadii = [ 130 ] # The PST + PixelLayerBuilder.BarrelAdditionalLayerType = [ 0 ] # -- will shift volume boundary to PST + PixelLayerBuilder.EndcapAdditionalLayerPositionsZ = [ -1900. , 1900. ] # DBM + PixelLayerBuilder.EndcapAdditionalLayerType = [ 1 , 1 ] # DBM + # Pixel barrel specifications + PixelLayerBuilder.BarrelLayerBinsZ = TrkDetFlags.PixelBarrelLayerMaterialBinsZ() + PixelLayerBuilder.BarrelLayerBinsPhi = TrkDetFlags.PixelBarrelLayerMaterialBinsPhi() + PixelLayerBuilder.EndcapLayerBinsR = TrkDetFlags.PixelEndcapLayerMaterialBinsR() + PixelLayerBuilder.EndcapLayerBinsPhi = TrkDetFlags.PixelEndcapLayerMaterialBinsPhi() + + # set the layer association + PixelLayerBuilder.SetLayerAssociation = setLayerAssociation + # output level + PixelLayerBuilder.OutputLevel = TrkDetFlags.PixelBuildingOutputLevel() + # the binning type of the layers + PixelLayerBinning = 2 + # add it to tool service + ToolSvc += PixelLayerBuilder + # put them to the caches + layerbuilders += [ PixelLayerBuilder ] + binnings += [ PixelLayerBinning ] + colors += [ 3 ] + + if DetFlags.SCT_on(): + # SCT building + from InDetTrackingGeometry.InDetTrackingGeometryConf import InDet__SiLayerBuilderCond + SCT_LayerBuilder = InDet__SiLayerBuilderCond(name=namePrefix+'SCT_LayerBuilderCond') + SCT_LayerBuilder.PixelCase = False + SCT_LayerBuilder.Identification = 'SCT' + SCT_LayerBuilder.SiDetManagerLocation = 'SCT' + # additionall layers - handle with care ! + SCT_LayerBuilder.EndcapAdditionalLayerPositionsZ = [ -2850 , 2850 ] + SCT_LayerBuilder.EndcapAdditionalLayerType = [ 0 , 0 ] + # SCT barrel specifications + SCT_LayerBuilder.BarrelLayerBinsZ = TrkDetFlags.SCT_BarrelLayerMaterialBinsZ() + SCT_LayerBuilder.BarrelLayerBinsPhi = TrkDetFlags.SCT_BarrelLayerMaterialBinsPhi() + # SCT endcap specifications + SCT_LayerBuilder.EndcapLayerBinsR = TrkDetFlags.SCT_EndcapLayerMaterialBinsR() + SCT_LayerBuilder.EndcapLayerBinsPhi = TrkDetFlags.SCT_EndcapLayerMaterialBinsPhi() + SCT_LayerBuilder.EndcapComplexRingBinning = TrkDetFlags.SCT_EndcapLayerDynamicRings() + # set the layer association + SCT_LayerBuilder.SetLayerAssociation = setLayerAssociation + # output level + SCT_LayerBuilder.OutputLevel = TrkDetFlags.SCT_BuildingOutputLevel() + # the binning type of the layer + SCT_LayerBinning = 2 + # SCT -> ToolSvc + ToolSvc += SCT_LayerBuilder + # put them to the caches + layerbuilders += [ SCT_LayerBuilder ] + binnings += [ SCT_LayerBinning ] + colors += [ 4 ] + + if DetFlags.TRT_on(): + from InDetTrackingGeometry.InDetTrackingGeometryConf import InDet__TRT_LayerBuilderCond + TRT_LayerBuilder = InDet__TRT_LayerBuilderCond(name=namePrefix+'TRT_LayerBuilderCond') + # TRT barrel specifications + TRT_LayerBuilder.ModelBarrelLayers = TrkDetFlags.TRT_BarrelModelLayers() + TRT_LayerBuilder.BarrelLayerBinsZ = TrkDetFlags.TRT_BarrelLayerMaterialBinsZ() + TRT_LayerBuilder.BarrelLayerBinsPhi = TrkDetFlags.TRT_BarrelLayerMaterialBinsPhi() + # SCT endcap specifications + TRT_LayerBuilder.ModelEndcapLayers = TrkDetFlags.TRT_EndcapModelLayers() + TRT_LayerBuilder.EndcapLayerBinsR = TrkDetFlags.TRT_EndcapLayerMaterialBinsR() + TRT_LayerBuilder.EndcapLayerBinsPhi = TrkDetFlags.TRT_EndcapLayerMaterialBinsPhi() + # set the binning from bi-aequidistant to arbitrary for complex TRT volumes + TRT_LayerBinning = 1 + if buildTrtStrawLayers or TrkDetFlags.TRT_BuildStrawLayers() : + TRT_LayerBinning = 2 + TRT_LayerBuilder.ModelLayersOnly = False + # output level + TRT_LayerBuilder.OutputLevel = TrkDetFlags.TRT_BuildingOutputLevel() + # TRT -> ToolSvc + ToolSvc += TRT_LayerBuilder + # put them to the caches + layerbuilders += [ TRT_LayerBuilder ] + binnings += [ TRT_LayerBinning ] + colors += [ 5 ] + + + # helpers for the InDetTrackingGeometry Builder : layer array creator + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__LayerArrayCreator + InDetLayerArrayCreator = Trk__LayerArrayCreator(name = 'InDetLayerArrayCreator') + InDetLayerArrayCreator.EmptyLayerMode = 2 # deletes empty material layers from arrays + InDetLayerArrayCreator.OutputLevel = TrkDetFlags.InDetBuildingOutputLevel() + # add to ToolSvc + ToolSvc += InDetLayerArrayCreator + + # helpers for the InDetTrackingGeometry Builder : volume array creator + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__TrackingVolumeArrayCreator + InDetTrackingVolumeArrayCreator = Trk__TrackingVolumeArrayCreator(name = 'InDetTrackingVolumeArrayCreator') + InDetTrackingVolumeArrayCreator.OutputLevel = TrkDetFlags.InDetBuildingOutputLevel() + # add to ToolSvc + ToolSvc += InDetTrackingVolumeArrayCreator + + # helpers for the InDetTrackingGeometry Builder : tracking voluem helper for glueing + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__TrackingVolumeHelper + InDetTrackingVolumeHelper = Trk__TrackingVolumeHelper(name ='InDetTrackingVolumeHelper') + InDetTrackingVolumeHelper.OutputLevel = TrkDetFlags.InDetBuildingOutputLevel() + # the material bins + InDetTrackingVolumeHelper.BarrelLayerBinsZ = TrkDetFlags.InDetPassiveLayerMaterialBinsRz() + InDetTrackingVolumeHelper.BarrelLayerBinsPhi = TrkDetFlags.InDetPassiveLayerMaterialBinsPhi() + InDetTrackingVolumeHelper.EndcapLayerBinsR = TrkDetFlags.InDetPassiveLayerMaterialBinsRz() + InDetTrackingVolumeHelper.EndcapLayerBinsPhi = TrkDetFlags.InDetPassiveLayerMaterialBinsPhi() + # add to ToolSvc + ToolSvc += InDetTrackingVolumeHelper + + # helpers for the InDetTrackingGeometry Builder : cylinder volume creator + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__CylinderVolumeCreator + InDetCylinderVolumeCreator = Trk__CylinderVolumeCreator(name = 'InDetCylinderVolumeCreator') + # give him the layer array creator + InDetCylinderVolumeCreator.LayerArrayCreator = InDetLayerArrayCreator + InDetCylinderVolumeCreator.TrackingVolumeArrayCreator = InDetTrackingVolumeArrayCreator + InDetCylinderVolumeCreator.TrackingVolumeHelper = InDetTrackingVolumeHelper + # specifiy the binning, passive layers, entry layers + InDetCylinderVolumeCreator.PassiveLayerThickness = TrkDetFlags.InDetPassiveLayerThickness() + InDetCylinderVolumeCreator.PassiveLayerBinsPhi = TrkDetFlags.InDetPassiveLayerMaterialBinsPhi() + InDetCylinderVolumeCreator.PassiveLayerBinsRZ = TrkDetFlags.InDetPassiveLayerMaterialBinsRz() + # output level + InDetCylinderVolumeCreator.OutputLevel = TrkDetFlags.InDetBuildingOutputLevel() + # add to ToolSvc + ToolSvc += InDetCylinderVolumeCreator + + # the envelope definition service + from SubDetectorEnvelopes.SubDetectorEnvelopesConf import DetDescrDBEnvelopeSvc + AtlasEnvelopeSvc = DetDescrDBEnvelopeSvc('AtlasEnvelopeSvcDefinitionSvc') + # set the output level for the Envelope service + AtlasEnvelopeSvc.OutputLevel = TrkDetFlags.InDetBuildingOutputLevel() + # add to SvcMgr + ServiceMgr += AtlasEnvelopeSvc + + # the tracking geometry builder + InDet__RobustTrackingGeometryBuilderCond.__init__(self,namePrefix+name,\ + BeamPipeBuilder = BeamPipeBuilder,\ + LayerBuilders = layerbuilders, + LayerBinningType = binnings, + ColorCodes = colors, + BarrelEntryLayers = [ 2, 2, 2 ], + EndcapEntryLayers = [ 1, 0, 1 ], + EnvelopeDefinitionSvc = AtlasEnvelopeSvc, + VolumeEnclosureDiscPositions = [ 3000., 3450. ], + TrackingVolumeCreator = InDetCylinderVolumeCreator, + LayerArrayCreator = InDetLayerArrayCreator, + BuildBoundaryLayers = TrkDetFlags.InDetBuildMaterialBoundaries(), + ReplaceAllJointBoundaries = TrkDetFlags.InDetBuildJointBoundaries(), + OutputLevel = TrkDetFlags.InDetBuildingOutputLevel(), + ExitVolumeName = TrkDetFlags.InDetContainerName(), + MagneticFieldMode = TrkDetFlags.MagneticFieldMode()) + + diff --git a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/python/ConfiguredStagedTrackingGeometryBuilderCond.py b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/python/ConfiguredStagedTrackingGeometryBuilderCond.py new file mode 100644 index 00000000000..07abdcbba39 --- /dev/null +++ b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/python/ConfiguredStagedTrackingGeometryBuilderCond.py @@ -0,0 +1,223 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + +###################################################### +# ConfiguredStagedTrackingGeometry module +# +# it inherits from RobustTrackingGeometryBuilderConf and performs +# standard configuration +# +###################################################### + +# import the Extrapolator configurable +from InDetTrackingGeometry.InDetTrackingGeometryConf import InDet__StagedTrackingGeometryBuilderCond + +# define the class +class ConfiguredStagedTrackingGeometryBuilderCond( InDet__StagedTrackingGeometryBuilderCond ): + # constructor + def __init__(self,name = 'InDetTrackingGeometryBuilderCond', + namePrefix = '', + setLayerAssociation = True, + buildTrtStrawLayers = False): + + # get the ToolSvc + from AthenaCommon.AppMgr import ToolSvc, ServiceMgr + from AthenaCommon.DetFlags import DetFlags + + # the Detector flags to be imported + from TrkDetDescrSvc.TrkDetDescrJobProperties import TrkDetFlags + + # beampipe + from InDetTrackingGeometry.InDetTrackingGeometryConf import InDet__BeamPipeBuilderCond + BeamPipeBuilder = InDet__BeamPipeBuilderCond(name=namePrefix+'BeamPipeBuilderCond') + BeamPipeBuilder.BeamPipeRadius = TrkDetFlags.BeamPipeRadius() + BeamPipeBuilder.BeamPipeThickness = TrkDetFlags.BeamPipeThickness() + BeamPipeBuilder.BeamPipeMaterialBinsZ = TrkDetFlags.BeamPipeLayerMaterialBinsZ() + BeamPipeBuilder.OutputLevel = TrkDetFlags.BeamPipeBuildingOutputLevel() + ToolSvc += BeamPipeBuilder + + # the layer providers + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__LayerProviderCond + BeamPipeProvider = Trk__LayerProviderCond(name=namePrefix+'BeamPipeProviderCond') + BeamPipeProvider.LayerBuilder = BeamPipeBuilder + ToolSvc += BeamPipeProvider + + # binning of the beam pipe + BeamPipeBinning = 2 + + # the layer builders + layerProviders = [ BeamPipeProvider ] + binningsCenter = [ BeamPipeBinning ] + binningsEndcap = [ BeamPipeBinning ] + colors = [ 2 ] + + # PIXEL building + if DetFlags.pixel_on() : + from InDetTrackingGeometry.InDetTrackingGeometryConf import InDet__SiLayerBuilderCond + PixelLayerBuilder = InDet__SiLayerBuilderCond(name=namePrefix+'PixelLayerBuilderCond') + PixelLayerBuilder.PixelCase = True + PixelLayerBuilder.Identification = 'Pixel' + PixelLayerBuilder.SiDetManagerLocation = 'Pixel' + # Pixel barrel specifications + PixelLayerBuilder.BarrelLayerBinsZ = TrkDetFlags.PixelBarrelLayerMaterialBinsZ() + PixelLayerBuilder.BarrelLayerBinsPhi = TrkDetFlags.PixelBarrelLayerMaterialBinsPhi() + PixelLayerBuilder.EndcapLayerBinsR = TrkDetFlags.PixelEndcapLayerMaterialBinsR() + PixelLayerBuilder.EndcapLayerBinsPhi = TrkDetFlags.PixelEndcapLayerMaterialBinsPhi() + PixelLayerBuilder.EndcapRingLayout = TrkDetFlags.PixelRingLayout() + # set the layer association + PixelLayerBuilder.SetLayerAssociation = setLayerAssociation + # output level + PixelLayerBuilder.OutputLevel = TrkDetFlags.PixelBuildingOutputLevel() + # the binning type of the layers + PixelLayerBinning = 2 + # add it to tool service + ToolSvc += PixelLayerBuilder + + # the layer providers + PixelLayerProvider = Trk__LayerProviderCond(name=namePrefix+'PixelLayerProviderCond') + PixelLayerProvider.LayerBuilder = PixelLayerBuilder + ToolSvc += PixelLayerProvider + layerProviders += [ PixelLayerProvider ] + binningsCenter += [ PixelLayerBinning ] + binningsEndcap += [ PixelLayerBinning ] + colors += [ 3 ] + + # SCT building + if DetFlags.SCT_on() : + SCT_LayerBuilder = InDet__SiLayerBuilderCond(name=namePrefix+'SCT_LayerBuilderCond') + SCT_LayerBuilder.PixelCase = False + SCT_LayerBuilder.Identification = 'SCT' + SCT_LayerBuilder.SiDetManagerLocation = 'SCT' + # additionall layers - handle with care ! + SCT_LayerBuilder.EndcapAdditionalLayerPositionsZ = [ -2850 , 2850 ] + SCT_LayerBuilder.EndcapAdditionalLayerType = [ 0 , 0 ] + # SCT barrel specifications + SCT_LayerBuilder.BarrelLayerBinsZ = TrkDetFlags.SCT_BarrelLayerMaterialBinsZ() + SCT_LayerBuilder.BarrelLayerBinsPhi = TrkDetFlags.SCT_BarrelLayerMaterialBinsPhi() + # SCT endcap specifications + SCT_LayerBuilder.EndcapLayerBinsR = TrkDetFlags.SCT_EndcapLayerMaterialBinsR() + SCT_LayerBuilder.EndcapLayerBinsPhi = TrkDetFlags.SCT_EndcapLayerMaterialBinsPhi() + SCT_LayerBuilder.EndcapComplexRingBinning = TrkDetFlags.SCT_EndcapLayerDynamicRings() + # set the layer association + SCT_LayerBuilder.SetLayerAssociation = setLayerAssociation + # output level + SCT_LayerBuilder.OutputLevel = TrkDetFlags.SCT_BuildingOutputLevel() + # the binning type of the layer + SCT_LayerBinning = 2 + # SCT -> ToolSvc + ToolSvc += SCT_LayerBuilder + + # the layer providers + SCT_LayerProvider = Trk__LayerProviderCond(name=namePrefix+'SCT_LayerProviderCond') + SCT_LayerProvider.LayerBuilder = SCT_LayerBuilder + ToolSvc += SCT_LayerProvider + + # put them to the caches + layerProviders += [ SCT_LayerProvider ] + binningsCenter += [ SCT_LayerBinning ] + binningsEndcap += [ SCT_LayerBinning ] + colors += [ 4 ] + + # TRT building + if DetFlags.TRT_on() : + from InDetTrackingGeometry.InDetTrackingGeometryConf import InDet__TRT_LayerBuilderCond + TRT_LayerBuilder = InDet__TRT_LayerBuilderCond(name=namePrefix+'TRT_LayerBuilderCond') + # TRT barrel specifications + TRT_LayerBuilder.ModelBarrelLayers = TrkDetFlags.TRT_BarrelModelLayers() + TRT_LayerBuilder.BarrelLayerBinsZ = TrkDetFlags.TRT_BarrelLayerMaterialBinsZ() + TRT_LayerBuilder.BarrelLayerBinsPhi = TrkDetFlags.TRT_BarrelLayerMaterialBinsPhi() + # SCT endcap specifications + TRT_LayerBuilder.ModelEndcapLayers = TrkDetFlags.TRT_EndcapModelLayers() + TRT_LayerBuilder.EndcapLayerBinsR = TrkDetFlags.TRT_EndcapLayerMaterialBinsR() + TRT_LayerBuilder.EndcapLayerBinsPhi = TrkDetFlags.TRT_EndcapLayerMaterialBinsPhi() + # set the binning from bi-aequidistant to arbitrary for complex TRT volumes + TRT_LayerBinning = 1 + if buildTrtStrawLayers or TrkDetFlags.TRT_BuildStrawLayers() : + TRT_LayerBinning = 2 + TRT_LayerBuilder.ModelLayersOnly = False + # output level + TRT_LayerBuilder.OutputLevel = TrkDetFlags.TRT_BuildingOutputLevel() + # TRT -> ToolSvc + ToolSvc += TRT_LayerBuilder + + + # the layer providers + TRT_LayerProvider = Trk__LayerProviderCond(name=namePrefix+'TRT_LayerProviderCond') + TRT_LayerProvider.LayerBuilder = TRT_LayerBuilder + ToolSvc += TRT_LayerProvider + + # put them to the caches + layerProviders += [ TRT_LayerProvider ] + binningsCenter += [ TRT_LayerBinning ] + binningsEndcap += [ TRT_LayerBinning ] + colors += [ 5 ] + + + # helpers for the InDetTrackingGeometry Builder : layer array creator + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__LayerArrayCreator + InDetLayerArrayCreator = Trk__LayerArrayCreator(name = 'InDetLayerArrayCreator') + InDetLayerArrayCreator.EmptyLayerMode = 2 # deletes empty material layers from arrays + InDetLayerArrayCreator.OutputLevel = TrkDetFlags.InDetBuildingHelperOutputLevel() + # add to ToolSvc + ToolSvc += InDetLayerArrayCreator + + # helpers for the InDetTrackingGeometry Builder : volume array creator + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__TrackingVolumeArrayCreator + InDetTrackingVolumeArrayCreator = Trk__TrackingVolumeArrayCreator(name = 'InDetTrackingVolumeArrayCreator') + InDetTrackingVolumeArrayCreator.OutputLevel = TrkDetFlags.InDetBuildingOutputLevel() + # add to ToolSvc + ToolSvc += InDetTrackingVolumeArrayCreator + + # helpers for the InDetTrackingGeometry Builder : tracking voluem helper for glueing + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__TrackingVolumeHelper + InDetTrackingVolumeHelper = Trk__TrackingVolumeHelper(name ='InDetTrackingVolumeHelper') + InDetTrackingVolumeHelper.OutputLevel = TrkDetFlags.InDetBuildingHelperOutputLevel() + # the material bins + InDetTrackingVolumeHelper.BarrelLayerBinsZ = TrkDetFlags.InDetPassiveLayerMaterialBinsRz() + InDetTrackingVolumeHelper.BarrelLayerBinsPhi = TrkDetFlags.InDetPassiveLayerMaterialBinsPhi() + InDetTrackingVolumeHelper.EndcapLayerBinsR = TrkDetFlags.InDetPassiveLayerMaterialBinsRz() + InDetTrackingVolumeHelper.EndcapLayerBinsPhi = TrkDetFlags.InDetPassiveLayerMaterialBinsPhi() + # add to ToolSvc + ToolSvc += InDetTrackingVolumeHelper + + # helpers for the InDetTrackingGeometry Builder : cylinder volume creator + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__CylinderVolumeCreator + InDetCylinderVolumeCreator = Trk__CylinderVolumeCreator(name = 'InDetCylinderVolumeCreator') + # give him the layer array creator + InDetCylinderVolumeCreator.LayerArrayCreator = InDetLayerArrayCreator + InDetCylinderVolumeCreator.TrackingVolumeArrayCreator = InDetTrackingVolumeArrayCreator + InDetCylinderVolumeCreator.TrackingVolumeHelper = InDetTrackingVolumeHelper + # specifiy the binning, passive layers, entry layers + InDetCylinderVolumeCreator.PassiveLayerThickness = TrkDetFlags.InDetPassiveLayerThickness() + InDetCylinderVolumeCreator.PassiveLayerBinsPhi = TrkDetFlags.InDetPassiveLayerMaterialBinsPhi() + InDetCylinderVolumeCreator.PassiveLayerBinsRZ = TrkDetFlags.InDetPassiveLayerMaterialBinsRz() + # output level + InDetCylinderVolumeCreator.OutputLevel = TrkDetFlags.InDetBuildingHelperOutputLevel() + # add to ToolSvc + ToolSvc += InDetCylinderVolumeCreator + + # the envelope definition service + from SubDetectorEnvelopes.SubDetectorEnvelopesConf import DetDescrDBEnvelopeSvc + AtlasEnvelopeSvc = DetDescrDBEnvelopeSvc('AtlasEnvelopeSvcDefinitionSvc') + # set the output level for the Envelope service + AtlasEnvelopeSvc.OutputLevel = TrkDetFlags.InDetBuildingHelperOutputLevel() + # add to SvcMgr + ServiceMgr += AtlasEnvelopeSvc + + # the tracking geometry builder + InDet__StagedTrackingGeometryBuilderCond.__init__(self,namePrefix+name,\ + LayerBuilders = layerProviders, + LayerBinningTypeCenter = binningsCenter, + LayerBinningTypeEndcap = binningsEndcap, + ColorCodes = colors, + EnvelopeDefinitionSvc = AtlasEnvelopeSvc, + VolumeEnclosureDiscPositions = [ 3000., 3450. ], + TrackingVolumeCreator = InDetCylinderVolumeCreator, + LayerArrayCreator = InDetLayerArrayCreator, + CheckForRingLayout = True, + BuildBoundaryLayers = TrkDetFlags.InDetBuildMaterialBoundaries(), + ReplaceAllJointBoundaries = TrkDetFlags.InDetBuildJointBoundaries(), + OutputLevel = TrkDetFlags.InDetBuildingOutputLevel(), + ExitVolumeName = TrkDetFlags.InDetContainerName(), + MagneticFieldMode = TrkDetFlags.MagneticFieldMode()) + + diff --git a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/BeamPipeBuilderCond.cxx b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/BeamPipeBuilderCond.cxx new file mode 100755 index 00000000000..b76e58c2528 --- /dev/null +++ b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/BeamPipeBuilderCond.cxx @@ -0,0 +1,170 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// BeamPipeBuilderCond.cxx, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#include "InDetTrackingGeometry/BeamPipeBuilderCond.h" +// Amg +#include "GeoPrimitives/GeoPrimitives.h" +// Trk inlcude +#include "TrkDetDescrUtils/GeometryStatics.h" +#include "TrkDetDescrUtils/BinUtility.h" +#include "TrkDetDescrGeoModelCnv/GeoShapeConverter.h" +#include "TrkGeometry/MaterialProperties.h" +#include "TrkGeometry/LayerMaterialProperties.h" +#include "TrkGeometry/BinnedLayerMaterial.h" +#include "TrkGeometry/HomogeneousLayerMaterial.h" +#include "TrkGeometry/CylinderLayer.h" +#include "TrkSurfaces/CylinderBounds.h" +// GeoModel include +#include "BeamPipeGeoModel/BeamPipeDetectorManager.h" +#include "GeoModelKernel/GeoTube.h" +// Gaudi +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/SystemOfUnits.h" + +// constructor +InDet::BeamPipeBuilderCond::BeamPipeBuilderCond(const std::string& t, const std::string& n, const IInterface* p) : + AthAlgTool(t,n,p), + m_beamPipeFromDb(true), + m_beamPipeMgr(0), + m_beamPipeMgrName("BeamPipe"), + m_beamPipeEnvelope(1.*Gaudi::Units::mm), + m_beamPipeOffsetX(0.*Gaudi::Units::mm), + m_beamPipeOffsetY(0.*Gaudi::Units::mm), + m_beamPipeRadius(33.1*Gaudi::Units::mm), + m_beamPipeHalflength(2.7*Gaudi::Units::m), + m_beamPipeThickness(1.*Gaudi::Units::mm), + m_beamPipeX0(352.8*Gaudi::Units::mm), + m_beamPipeL0(407.*Gaudi::Units::mm), + //m_beamPipedEdX(0.2945*Gaudi::Units::MeV/Gaudi::Units::mm), + m_beamPipeA(9.012), + m_beamPipeZ(4.), + m_beamPipeRho(1.848e-3), + m_beamPipeBinsZ(1), + m_identification("BeamPipe") +{ + declareInterface<Trk::ILayerBuilderCond>(this); + declareProperty("BeamPipeFromGeoModel" , m_beamPipeFromDb); + declareProperty("BeamPipeManager" , m_beamPipeMgrName); + declareProperty("BeamPipeEnvelope" , m_beamPipeEnvelope); + // --------------------- by hand properties of the beam pipe itself -- // + declareProperty("BeamPipeOffsetX" , m_beamPipeOffsetX); + declareProperty("BeamPipeOffsetY" , m_beamPipeOffsetY); + declareProperty("BeamPipeRadius" , m_beamPipeRadius); + declareProperty("BeamPipeHalflength" , m_beamPipeHalflength); + declareProperty("BeamPipeThickness" , m_beamPipeThickness); + // --------------------- by hand material properties ---------------- // + declareProperty("BeamPipeX0" , m_beamPipeX0); + declareProperty("BeamPipeAverageA" , m_beamPipeA); + declareProperty("BeamPipeAverageZ" , m_beamPipeZ); + declareProperty("BeamPipeAverageRho" , m_beamPipeRho); + // Material bins + declareProperty("BeamPipeMaterialBinsZ", m_beamPipeBinsZ); + // identification + declareProperty("Identification" , m_identification); +} + +// destructor +InDet::BeamPipeBuilderCond::~BeamPipeBuilderCond() +{} + +// Athena standard methods +// initialize +StatusCode InDet::BeamPipeBuilderCond::initialize() +{ + if (m_beamPipeFromDb && detStore()->retrieve(m_beamPipeMgr,m_beamPipeMgrName).isFailure()){ + ATH_MSG_ERROR("Could not retrieve BeamPipe detector manager '" << m_beamPipeMgrName << "'." ); + return StatusCode::FAILURE; + } else if (m_beamPipeFromDb) + ATH_MSG_DEBUG("Successfully retrieved BeamPipe detector manager '" << m_beamPipeMgrName << "'." ); + + ATH_MSG_DEBUG( "initialize()" ); + return StatusCode::SUCCESS; +} + +// finalize +StatusCode InDet::BeamPipeBuilderCond::finalize() +{ + ATH_MSG_DEBUG( "finalize() successful" ); + return StatusCode::SUCCESS; +} + + +/** LayerBuilder interface method - returning Barrel-like layers */ +//TODO: context is not used, beamPipe retrieved from manager. range is infinite +std::pair<EventIDRange, const std::vector< const Trk::CylinderLayer* >*> InDet::BeamPipeBuilderCond::cylindricalLayers(const EventContext&) const +{ + + std::vector<const Trk::CylinderLayer*>* beamPipe = new std::vector<const Trk::CylinderLayer*>; + + // the geometry + Amg::Transform3D* beamPipeTransform = new Amg::Transform3D; + beamPipeTransform->setIdentity(); + + double beamPipeRadius = m_beamPipeRadius; + + if (m_beamPipeMgr){ + // get the central top volume + PVConstLink beamPipeTopVolume = m_beamPipeMgr->getTreeTop(0); + (*beamPipeTransform) = Amg::Translation3D(beamPipeTopVolume->getX().translation().x(), + beamPipeTopVolume->getX().translation().y(), + beamPipeTopVolume->getX().translation().z()); + const GeoLogVol* beamPipeLogVolume = beamPipeTopVolume->getLogVol(); + const GeoTube* beamPipeTube = 0; + if (beamPipeLogVolume){ + // get the geoShape and translate + Trk::GeoShapeConverter geoShaper; + beamPipeTube = dynamic_cast<const GeoTube*>(beamPipeLogVolume->getShape()); + if (beamPipeTube) + beamPipeRadius = beamPipeTube->getRMax()-m_beamPipeEnvelope; + } + ATH_MSG_VERBOSE("BeamPipe constructed from Database: translation (yes) - radius "<< ( beamPipeTube ? "(yes)" : "(no)") << " - r = " << beamPipeRadius ); + } else + (*beamPipeTransform) = Amg::Translation3D(m_beamPipeOffsetX, m_beamPipeOffsetY, 0.); + + ATH_MSG_VERBOSE("BeamPipe shift estimated as : " + << beamPipeTransform->translation().x() << ", " + << beamPipeTransform->translation().y() << "," + << beamPipeTransform->translation().y()); + + Trk::CylinderBounds* beamPipeBounds = new Trk::CylinderBounds(beamPipeRadius, m_beamPipeHalflength); + ATH_MSG_VERBOSE("BeamPipe bounds constructed as : " << (*beamPipeBounds) ); + + // the material + Trk::MaterialProperties beamPipeMaterial(m_beamPipeThickness, + m_beamPipeX0, + m_beamPipeL0, + m_beamPipeA, + m_beamPipeZ, + m_beamPipeRho); + + // binned layer material for the beam pipe possible + Trk::LayerMaterialProperties* beamPipeLayerMaterial=0; + if ( m_beamPipeBinsZ == 1) + beamPipeLayerMaterial = new Trk::HomogeneousLayerMaterial(beamPipeMaterial, 1.0); + else { + Trk::BinUtility layerBinUtility(m_beamPipeBinsZ, -m_beamPipeHalflength, m_beamPipeHalflength, Trk::open, Trk::binZ ); + beamPipeLayerMaterial = new Trk::BinnedLayerMaterial(layerBinUtility); + } + + ATH_MSG_DEBUG( "BeamPipe constructed with material-properties: " << beamPipeMaterial ); + + beamPipe->push_back(new Trk::CylinderLayer(beamPipeTransform, + beamPipeBounds, + *beamPipeLayerMaterial, + m_beamPipeThickness)); + //delete beamPipeLayerMaterial; + + //create dummy infinite range + EventIDRange range; + return std::make_pair(range,beamPipe); + +} + + + + diff --git a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/RobustTrackingGeometryBuilderCond.cxx b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/RobustTrackingGeometryBuilderCond.cxx new file mode 100755 index 00000000000..42134152779 --- /dev/null +++ b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/RobustTrackingGeometryBuilderCond.cxx @@ -0,0 +1,771 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +//////////////////////////////////////////////////////////////////// +// RobustTrackingGeometryBuilderCond.cxx, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +// InDet +#include "InDetTrackingGeometry/RobustTrackingGeometryBuilderCond.h" +// EnvelopeDefinitionService +#include "SubDetectorEnvelopes/IEnvelopeDefSvc.h" +// Trk interfaces +#include "TrkDetDescrInterfaces/ILayerBuilderCond.h" +#include "TrkDetDescrInterfaces/ITrackingVolumeCreator.h" +#include "TrkDetDescrInterfaces/ILayerArrayCreator.h" +// Trk Geometry stuff +#include "TrkDetDescrUtils/BinnedArray.h" +#include "TrkVolumes/VolumeBounds.h" +#include "TrkVolumes/CylinderVolumeBounds.h" +#include "TrkGeometry/TrackingVolume.h" +#include "TrkGeometry/TrackingGeometry.h" +#include "TrkGeometry/MagneticFieldProperties.h" +#include "TrkGeometry/Material.h" +#include "TrkGeometry/Layer.h" +#include "TrkGeometry/CylinderLayer.h" +#include "TrkGeometry/DiscLayer.h" +#include "TrkSurfaces/DiscBounds.h" +//Gaudi +#include "GaudiKernel/SystemOfUnits.h" +#include "GaudiKernel/MsgStream.h" + +// constructor +InDet::RobustTrackingGeometryBuilderCond::RobustTrackingGeometryBuilderCond(const std::string& t, const std::string& n, const IInterface* p) : + AthAlgTool(t,n,p), + Trk::TrackingVolumeManipulator(), + m_beamPipeBuilder("InDet::BeamPipeBuilder/AtlasBeamPipeBuilder"), + m_trackingVolumeCreator("Trk::CylinderVolumeCreator/CylinderVolumeCreator"), + m_layerArrayCreator("Trk::LayerArrayCreator/LayerArrayCreator"), + m_enclosingEnvelopeSvc("AtlasEnvelopeDefSvc", n), + m_layerEnvelopeCover(2*Gaudi::Units::mm), + m_buildBoundaryLayers(true), + m_replaceJointBoundaries(true), + m_materialProperties(0), + m_magneticFieldProperties(0), + m_outwardsFraction(0.75), + m_indexStaticLayers(true), + m_namespace("InDet::"), + m_exitVolume("InDet::Containers::InnerDetector") +{ + declareInterface<Trk::IGeometryBuilderCond>(this); + // layer builders and their configurations + declareProperty("BeamPipeBuilder", m_beamPipeBuilder); + declareProperty("LayerBuilders", m_layerBuilders); + declareProperty("LayerBinningType", m_layerBinningType); + declareProperty("ColorCodes", m_colorCodesConfig); + // envelope definition service + declareProperty("EnvelopeDefinitionSvc", m_enclosingEnvelopeSvc ); + declareProperty("VolumeEnclosureCylinderRadii", m_enclosingCylinderRadius); + declareProperty("VolumeEnclosureDiscPositions", m_enclosingDiscPositionZ); + // helper tools + declareProperty("TrackingVolumeCreator", m_trackingVolumeCreator); + declareProperty("LayerArrayCreator", m_layerArrayCreator); + // build the Boundary Layers + declareProperty("EnvelopeCover", m_layerEnvelopeCover); + declareProperty("BuildBoundaryLayers", m_buildBoundaryLayers); + declareProperty("ReplaceAllJointBoundaries", m_replaceJointBoundaries); + // outer envelope to + declareProperty("OutwardsFraction", m_outwardsFraction); + // force robust layer indexing + declareProperty("IndexStaticLayers", m_indexStaticLayers); + // volume namespace & contaienr name + declareProperty("VolumeNamespace", m_namespace); + declareProperty("ExitVolumeName", m_exitVolume); + declareProperty("isSLHC", m_isSLHC=false); +} + +// destructor +InDet::RobustTrackingGeometryBuilderCond::~RobustTrackingGeometryBuilderCond() +{ + delete m_materialProperties; + delete m_magneticFieldProperties; +} + +// Athena standard methods +// initialize +StatusCode InDet::RobustTrackingGeometryBuilderCond::initialize() +{ + + // retrieve envelope definition service -------------------------------------------------- + if ( m_enclosingEnvelopeSvc.retrieve().isFailure() ){ + ATH_MSG_FATAL( "Could not retrieve EnvelopeDefinition service. Abort."); + return StatusCode::FAILURE; + } + + // Retrieve the beampipe builders -------------------------------------------------------- + if (m_beamPipeBuilder.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool(s) " << m_beamPipeBuilder ); + return StatusCode::FAILURE; + } else + ATH_MSG_DEBUG( "Retrieved tool " << m_beamPipeBuilder ); + + // Retrieve the layer builders ----------------------------------------------------------- + if (m_layerBuilders.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool(s) " << m_layerBuilders ); + return StatusCode::FAILURE; + } else + ATH_MSG_DEBUG( "Retrieved tool " << m_layerBuilders ); + + // Retrieve the tracking volume creator ------------------------------------------------- + if (m_trackingVolumeCreator.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool " << m_trackingVolumeCreator ); + return StatusCode::FAILURE; + } else + ATH_MSG_DEBUG( "Retrieved tool " << m_trackingVolumeCreator ); + + // Retrieve the layer array creator ---------------------------------------------------- + if (m_layerArrayCreator.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool " << m_layerArrayCreator ); + return StatusCode::FAILURE; + } else + ATH_MSG_INFO( "Retrieved tool " << m_layerArrayCreator ); + + // Dummy MaterialProerties + m_materialProperties = new Trk::Material; + + ATH_MSG_INFO( "initialize() succesful" ); + + return StatusCode::SUCCESS; +} + + +std::pair<EventIDRange, const Trk::TrackingGeometry*> InDet::RobustTrackingGeometryBuilderCond::trackingGeometry(const EventContext& ctx, std::pair<EventIDRange, const Trk::TrackingVolume*>) const +{ + // only one assumption: + // layer builders are ordered in increasing r + + //////////////////////////////////////////////////////////////////////////////////////////////////////// + // The Overall Geometry + + Trk::TrackingGeometry* trackingGeometry = 0; + + // retrieve all the layers and sort them + unsigned int numLayBuilders = m_layerBuilders.size(); + + // central sector extend + double centralExtendZ = 0.; + // endcap extends + double endcapMaxExtend = 0.; + double endcapMinExtend = 10e10; + // and the overallExtend(s) + double overallExtendZ = 0.; + double overallRmin = 10e10; + double overallRmax = 0.; + + // cylinder layers at growing radii + std::vector< std::vector< const Trk::Layer*> > providedCylinderLayers; + providedCylinderLayers.reserve(numLayBuilders); + std::vector< double > cylinderInnerRadii(numLayBuilders,10e10); + std::vector< double > cylinderOuterRadii(numLayBuilders,0.); + std::vector< double > cylinderExtendsInZ(numLayBuilders,0.); + + // negative disc layers and positive disc layers + std::vector< std::vector< const Trk::Layer*> > providedDiscLayersNeg; + std::vector< std::vector< const Trk::Layer*> > providedDiscLayersPos; + providedDiscLayersNeg.reserve(numLayBuilders); + providedDiscLayersPos.reserve(numLayBuilders); + std::vector< double > discInnerRadii(numLayBuilders,10e10); + std::vector< double > discOuterRadii(numLayBuilders,0.); + std::vector< double > discMinZ(numLayBuilders,10e10); + std::vector< double > discMaxZ(numLayBuilders,0.); + + //Start with a range covering 0 - inf, then narrow down + EventIDRange range; + + // (I) PARSE THE LAYERS FOR OVERALL DIMENSIONS ------------------------------------------------------------- + ATH_MSG_DEBUG( "[ STEP 1 ] : Parse the provided layers for the dimensions." ); + // fill the layers into the vectors + for ( unsigned int ilb = 0; ilb < m_layerBuilders.size(); ++ilb){ + + Trk::BinningType binningType = (m_layerBinningType.size() == m_layerBuilders.size()) ? + (Trk::BinningType)m_layerBinningType[ilb] : Trk::arbitrary; + + // retrieve the cylinder and disc layers + ATH_MSG_DEBUG( "[ LayerBuilder : '" << m_layerBuilders[ilb]->identification() << "' ] being processed. " ); + // (a) cylinder + std::pair<EventIDRange, const std::vector<const Trk::CylinderLayer*>*> cylinderLayersPair = m_layerBuilders[ilb]->cylindricalLayers(ctx); + auto cylinderLayers = cylinderLayersPair.second; + // (a) + std::vector<const Trk::Layer*> cylinderVolumeLayers; + if (cylinderLayers && cylinderLayers->size()){ + range=EventIDRange::intersect(range,cylinderLayersPair.first); + // screen output + ATH_MSG_DEBUG( " Processing CylinderLayers : " ); + // the ones to be filled into the double-vector + for (auto& cylIter : *cylinderLayers){ + // get the CylinderBounds + const Trk::CylinderBounds& cylBounds = (cylIter)->surfaceRepresentation().bounds(); + double currentR = cylBounds.r(); + // rmin/rmax with thicknes in mind + double currentRmin = binningType!=Trk::biequidistant ? + currentR - 0.5*(cylIter)->thickness()-m_layerEnvelopeCover : currentR + 0.5*(cylIter)->thickness()-m_layerEnvelopeCover; + double currentRmax = currentR + 0.5*(cylIter)->thickness() + m_layerEnvelopeCover; + // safe + double extendZ = cylIter->surfaceRepresentation().center().z() < 0. ? + fabs(cylIter->surfaceRepresentation().center().z() - cylBounds.halflengthZ())-m_layerEnvelopeCover: + cylIter->surfaceRepresentation().center().z() + cylBounds.halflengthZ() + m_layerEnvelopeCover; + // note the dimension + takeSmaller(cylinderInnerRadii[ilb],currentRmin); takeBigger(cylinderOuterRadii[ilb],currentRmax); + takeBigger(cylinderExtendsInZ[ilb],extendZ); + // push it into the vector + cylinderVolumeLayers.push_back(cylIter); + // overall dimensions + takeSmaller(overallRmin,currentRmin); takeBigger(overallRmax,currentRmax); + takeBigger(centralExtendZ, extendZ); + // in case no disc layers are provided + takeBigger(overallExtendZ,centralExtendZ); + } + // special treatment for bi-equidistant binning - a navigation layer will be added before and after the layers + if (binningType==Trk::biequidistant){ + double rStep = (cylinderOuterRadii[ilb]-cylinderInnerRadii[ilb])/(cylinderLayers->size()-1); + ATH_MSG_VERBOSE( " -> bi-equidistant : rStep estimated as " << rStep); + cylinderInnerRadii[ilb] -= rStep; cylinderOuterRadii[ilb] += rStep; + takeBigger(overallRmax,cylinderOuterRadii[ilb]); + } + ATH_MSG_VERBOSE( " -> yield (rMin/rMax/halflengthZ) = " + << cylinderInnerRadii[ilb] << " / " << cylinderOuterRadii[ilb] << " / " << cylinderExtendsInZ[ilb] ); + + } else + ATH_MSG_DEBUG( " No cylindrical layers processed." ); + + providedCylinderLayers.push_back(cylinderVolumeLayers); + // if after parsing of cylinder layers the maximal extend of cylinders is bigger than the minmal of discs + // reset the disc min extend (tiple will be swallowed)! + endcapMinExtend = ( centralExtendZ > endcapMinExtend) ? 10e10 : endcapMinExtend; + + // (b) discs + std::pair<EventIDRange, const std::vector<const Trk::DiscLayer*>*> discLayersPair = m_layerBuilders[ilb]->discLayers(ctx); + auto discLayers = discLayersPair.second; + std::vector<const Trk::Layer*> discVolumeLayersNeg; + std::vector<const Trk::Layer*> discVolumeLayersPos; + if (discLayers && discLayers->size()){ + range=EventIDRange::intersect(range,discLayersPair.first); + // screen output + ATH_MSG_DEBUG( " Processing DiscLayers : " ); + for (auto& discIter : *discLayers){ + // get the DiscBounds + const Trk::DiscBounds* discBounds = dynamic_cast<const Trk::DiscBounds*> + (&(discIter->surfaceRepresentation().bounds())); + // get the current Z min/max + double discZ = discIter->surfaceRepresentation().center().z(); + double currentZmin = binningType!=Trk::biequidistant ? (discZ-0.5*discIter->thickness()) : (discZ+0.5*discIter->thickness()); + double currentZmax = discZ+0.5*discIter->thickness(); + // force it to be symmetrized + if (currentZmax > 0.){ + takeSmaller(discMinZ[ilb],currentZmin); takeBigger(discMaxZ[ilb], currentZmax); + // push it into the vector + discVolumeLayersPos.push_back(discIter); + } else { + // in symmetrized setup only interested in total numbers + double negMinZ = fabs(currentZmax); + double negMaxZ = fabs(currentZmin); + takeSmaller(discMinZ[ilb],negMinZ); takeBigger(discMaxZ[ilb],negMaxZ); + // push it into the vector + discVolumeLayersNeg.push_back(discIter); + } + + // radial dimensions + if (discBounds){ + double currentRmin = discBounds->rMin(); + double currentRmax = discBounds->rMax(); + // note the dimension + takeSmaller(discInnerRadii[ilb], currentRmin); takeBigger(discOuterRadii[ilb],currentRmax); + // overall dimensions + takeSmaller(overallRmin, currentRmin); takeBigger(overallRmax, currentRmax); + } + // min/max extend of the discs + takeSmaller(endcapMinExtend, discMinZ[ilb]); takeBigger(endcapMaxExtend, discMaxZ[ilb]); + takeBigger(overallExtendZ, endcapMaxExtend); + } + // special treatment for bi-equidistant binning - a navigation layer will be added before and after the layers + if (binningType==Trk::biequidistant){ + double zStep = (discMaxZ[ilb]-discMinZ[ilb])/(discLayers->size()/2-1); + discMinZ[ilb] -= zStep; + discMaxZ[ilb] += zStep; + takeBigger(overallExtendZ,discMaxZ[ilb]); + } + + ATH_MSG_VERBOSE( " -> yield (rMin/rMax/zMin/zMax) = " + << discInnerRadii[ilb] << " / " << discOuterRadii[ilb] << " / " << discMinZ[ilb] << " / " << discMaxZ[ilb] ); + + } else + ATH_MSG_DEBUG( " No disk-like layers processed." ); + + + // fill the layers into the double-vector + providedDiscLayersNeg.push_back(discVolumeLayersNeg); + providedDiscLayersPos.push_back(discVolumeLayersPos); + + // memory cleanup + delete discLayers; + delete cylinderLayers; + + if (msgLvl(MSG::VERBOSE)){ + // summary after this step + ATH_MSG_VERBOSE( "[ Summary STEP 1 ---------------------------------------- ] " ); + ATH_MSG_VERBOSE( " overall minimum r : " << overallRmin ); + ATH_MSG_VERBOSE( " overall maximum r : " << overallRmax ); + ATH_MSG_VERBOSE( " overall z extend : " << overallExtendZ ); + ATH_MSG_VERBOSE( " central sector z extend : " << centralExtendZ ); + ATH_MSG_VERBOSE( " maximum endcap z extend : " << endcapMaxExtend ); + ATH_MSG_VERBOSE( " minimum endcap z extend : " << endcapMinExtend ); + } + + } + + + // (II) update the positions ------------------------------------------------------------ + ATH_MSG_DEBUG( "[ STEP 2 ] : Closing the gaps from the parsed original dimensions." ); + // i.e. close the gap + double oldCeZ = centralExtendZ; + centralExtendZ = 0.5*(endcapMinExtend+oldCeZ); + endcapMinExtend = centralExtendZ; + + ATH_MSG_DEBUG( " central sector extend in z recalculated to be " << centralExtendZ << " (was " << oldCeZ << ")" ); + + // (III) create the sub volumes ------------------------------------------------------------- + ATH_MSG_DEBUG( "[ STEP 3 ] : Create the sub volumes." ); + + std::vector<const Trk::TrackingVolume*> centralSectorVolumes; + std::vector<const Trk::TrackingVolume*> negativeSectorVolumes; + std::vector<const Trk::TrackingVolume*> positiveSectorVolumes; + + // -------------------------------------------------------------------------------------------------- + // first the beampipe volume + Trk::TrackingVolume* beamPipeVolume = 0; + // the Volume Bounds + Trk::CylinderVolumeBounds* beamPipeBounds = new Trk::CylinderVolumeBounds(overallRmin,overallExtendZ); + // BinnedArray needed + Trk::BinnedArray<Trk::Layer>* beamPipeLayerArray = 0; + std::pair<EventIDRange,const std::vector<const Trk::CylinderLayer*>*> beamPipeVecPair = m_beamPipeBuilder->cylindricalLayers(ctx); + auto beamPipeVec = beamPipeVecPair.second; + if (beamPipeVec->size()){ + range=EventIDRange::intersect(range,beamPipeVecPair.first); + beamPipeLayerArray = m_layerArrayCreator->cylinderLayerArray(*beamPipeVec,0.,beamPipeBounds->outerRadius(),Trk::arbitrary); + } + delete beamPipeVec; + // create the TrackingVolume + beamPipeVolume = new Trk::TrackingVolume(0, + beamPipeBounds, + *m_materialProperties, + beamPipeLayerArray, + 0, + "InDet::BeamPipe"); + // set the color code + beamPipeVolume->registerColorCode(46); + + // beampipe + detectors / prepared + std::vector<const Trk::TrackingVolume*> idVolumes; + idVolumes.push_back(beamPipeVolume); + + // -------------------------------------------------------------------------------------------------- + double lastCentralOuterR = beamPipeBounds->outerRadius(); + double lastNegEndcapOuterR = beamPipeBounds->outerRadius(); + double lastPosEndcapOuterR = beamPipeBounds->outerRadius(); + + // loop over double-vectors, access the dimensions from the parsing + auto pclIter = providedCylinderLayers.begin(); + auto pclEnd = providedCylinderLayers.end(); + auto pndlIter = providedDiscLayersNeg.begin(); + auto pndlEnd = providedDiscLayersNeg.end(); + auto ppdlIter = providedDiscLayersPos.begin(); + auto ppdlEnd = providedDiscLayersPos.end(); + + // the number of layer builders + unsigned int numLayerBuilders = m_layerBuilders.size(); + + // loop over the prepared volumes + for ( unsigned int ilb=0 ; pclIter != pclEnd && pndlIter != pndlEnd && ppdlIter != ppdlEnd; + ++pclIter, ++pndlIter, ++ppdlIter, ++ilb) + { + // color code configuration (from jobOptions/declareProperty interface) + int colorCode = (m_colorCodesConfig.size() == numLayerBuilders) ? m_colorCodesConfig[ilb] : 21; + + Trk::BinningType binningType = (m_layerBinningType.size() == numLayerBuilders) ? + (Trk::BinningType)m_layerBinningType[ilb] : Trk::arbitrary; + + // volume name base + std::string baseName = m_layerBuilders[ilb]->identification(); + ATH_MSG_DEBUG( "[ Volume Creation : '" << baseName << "'] carried out." ); + ATH_MSG_DEBUG( " + color code : " << colorCode ); + + // maxmmal z extend for volume set & endcap inner z + double currentSetExtendZ = ( (*pndlIter).size() || (*ppdlIter).size() ) ? discMaxZ[ilb] : cylinderExtendsInZ[ilb]; + double currentEndcapInnerZ = ( (*pndlIter).size() || (*ppdlIter).size() ) ? discMinZ[ilb] : currentSetExtendZ; + + // radii for the sectors + double currentCentralOuterR = 0.; + double currentEndcapOuterR = 0.; + + if (m_isSLHC){ + double NextInnerRadii = ((ilb!=cylinderOuterRadii.size()-1) && cylinderInnerRadii[ilb+1]<discInnerRadii[ilb+1]) ? cylinderInnerRadii[ilb+1] : discInnerRadii[ilb+1]; + currentCentralOuterR = (ilb!=cylinderOuterRadii.size()-1) ? 0.5*(NextInnerRadii+cylinderOuterRadii[ilb]) : overallRmax; + currentEndcapOuterR = (ilb!=discOuterRadii.size()-1) ? 0.5*(NextInnerRadii+discOuterRadii[ilb]) : overallRmax; + } else{ + // we build from inside to outside, don't take middle position, but tend towards outer extend + currentCentralOuterR = (ilb!=cylinderOuterRadii.size()-1) ? (m_outwardsFraction*cylinderInnerRadii[ilb+1]+(1.-m_outwardsFraction)*cylinderOuterRadii[ilb]) : overallRmax; + currentEndcapOuterR = (ilb!=discOuterRadii.size()-1) ? (m_outwardsFraction*discInnerRadii[ilb+1]+(1.-m_outwardsFraction)*discOuterRadii[ilb]) : overallRmax; + + } + + ATH_MSG_VERBOSE( " + checking the sector boundaries : " ); + ATH_MSG_VERBOSE( " central sector ext. z (boundary) = " << currentSetExtendZ + << " (" << centralExtendZ << ")" ); + ATH_MSG_VERBOSE( " + current volume radii rMax (c/d) = " << currentCentralOuterR + << " / " << currentEndcapOuterR ); + // estimate the case + // cases are : + enum PackCase { contained, radial, central, split }; + // 0 - both cylinders and disc are contained in the central sector + // 1 - radial packing, volumes can't be put in in central / ec sectors + // 2 - only central sector exists + // 3 - standard ecn / central / ecp sectors split + bool endcapsExist = (*pndlIter).size() && (*ppdlIter).size() ; + // case flag set + PackCase caseFlag = (currentSetExtendZ < centralExtendZ && endcapsExist) ? contained : split; + if (currentSetExtendZ > centralExtendZ && currentEndcapInnerZ < centralExtendZ && endcapsExist) caseFlag = radial; + if (!endcapsExist) caseFlag = central; + + // case 0 and 1 can be handled together : + if ( caseFlag == contained || caseFlag == radial ){ + // create the volume sizes for the compact volume + double currentCentralExtendZ = 0.5*(cylinderExtendsInZ[ilb]+discMinZ[ilb]); + double currentExtendZ = contained ? centralExtendZ : overallExtendZ; + // in the radial wrapping case : take the smaller radius, assumes that packing is possible + double currentOuterR = currentCentralOuterR < currentEndcapOuterR ? currentCentralOuterR : currentEndcapOuterR; + // create the tiple container + const Trk::TrackingVolume* tripleContainer = packVolumeTriple((*pndlIter), + (*pclIter), + (*ppdlIter), + lastCentralOuterR, currentOuterR, + currentExtendZ,currentCentralExtendZ, + baseName, + colorCode, + binningType); + + + // cache the last central / ec outer radius + lastCentralOuterR = currentOuterR; + if (contained){ + ATH_MSG_VERBOSE( " + case I : provided cylinder and disc layers are entirely contained in central sector." ); + // and push the centralSectorVolumes + centralSectorVolumes.push_back(tripleContainer); + } else { + ATH_MSG_VERBOSE( " + case II : split into negative - central - positive sectors doesn't work, radial wrapping" ); + // cache the laster endcap radii (need to be equal since this is radially wrapped) + lastNegEndcapOuterR = currentOuterR; + lastPosEndcapOuterR = currentOuterR; + // the triple goes into the radial packing volumes + idVolumes.push_back(tripleContainer); + } + // case 2 and 3 + } else { + // output for case 3 and 4 + if (!endcapsExist) + ATH_MSG_VERBOSE( " + case III : only central sector." ); + else + ATH_MSG_VERBOSE( " + case IV : split into negative - central - positive sectors." ); + // build the name + std::string volumeBase = m_namespace+"Detectors::"+baseName; + // cylinder layers exist ------------------------------- + if ((*pclIter).size()){ + + ATH_MSG_VERBOSE( " -> central sector is being build." ); + // create the cylinder barrel + const Trk::TrackingVolume* barrel = + m_trackingVolumeCreator->createTrackingVolume((*pclIter), + *m_materialProperties, + lastCentralOuterR,currentCentralOuterR, + -centralExtendZ,centralExtendZ, + volumeBase+"::Barrel", + binningType); + // register the color code + barrel->registerColorCode(colorCode); + // cache the last ones + lastCentralOuterR = currentCentralOuterR; + // and push the centralSectorVolumes + centralSectorVolumes.push_back(barrel); + } + + // negative disc layers exist ------------------------------ + if ((*pndlIter).size()){ + + ATH_MSG_VERBOSE( " -> negative endcap is being build." ); + // create the cylinder barrel + const Trk::TrackingVolume* negEndcap = + m_trackingVolumeCreator->createTrackingVolume((*pndlIter), + *m_materialProperties, + lastNegEndcapOuterR,currentEndcapOuterR, + -overallExtendZ, -endcapMinExtend, + volumeBase+"::NegativeEndcap", + binningType); + // register the color code + negEndcap->registerColorCode(colorCode); + // cache the last ones + lastNegEndcapOuterR = currentEndcapOuterR; + // and push the negativeSectorVolumes + negativeSectorVolumes.push_back(negEndcap); + } + // positive disc layers exist -------------------------------- + if ((*ppdlIter).size()){ + + ATH_MSG_VERBOSE( " -> positive endcap is being build." ); + // create the cylinder barrel + const Trk::TrackingVolume* posEndcap = + m_trackingVolumeCreator->createTrackingVolume((*ppdlIter), + *m_materialProperties, + lastPosEndcapOuterR,currentEndcapOuterR, + endcapMinExtend,overallExtendZ, + volumeBase+"::PositiveEndcap", + binningType); + // register the color code + posEndcap->registerColorCode(colorCode); + // cache the last ones + lastPosEndcapOuterR = currentEndcapOuterR; + // and push the positiveSectorVolumes + positiveSectorVolumes.push_back(posEndcap); + } + } + } + + // (IV) create the container --------------------------------------------------------- + ATH_MSG_DEBUG( "[ STEP 4 ] : Create the container volume" ); + + bool enclose = (!m_enclosingEnvelopeSvc.empty()); + + const Trk::TrackingVolume* detectorContainer = packVolumeTriple(negativeSectorVolumes, + centralSectorVolumes, + positiveSectorVolumes, + "Container"); + + // get the dimensions from the envelope service + RZPairVector& envelopeDefs = m_enclosingEnvelopeSvc->getInDetRZValues(); + ATH_MSG_VERBOSE(" -> retrieved Inner Detector envelope definitions at size " << envelopeDefs.size()); + double enclosingVolumeRadius = envelopeDefs[1].first; + double enclosingVolumeHalfZ = fabs(envelopeDefs[1].second); + + // central enclosure volume + const Trk::TrackingVolume* centralEnclosure = enclose ? + m_trackingVolumeCreator->createGapTrackingVolume(*m_materialProperties, + overallRmax, enclosingVolumeRadius, + -overallExtendZ, overallExtendZ, + 1, true, + m_namespace+"Gaps::CentralEnclosure") : 0; + + // push the detector container into the ID volumes + idVolumes.push_back(detectorContainer); + if (centralEnclosure) idVolumes.push_back(centralEnclosure); + + std::string volumeName = enclose ? "InDet::Detectors::BpPixSctTrt" : m_exitVolume; + + ATH_MSG_VERBOSE(" -> inserting beam pipe into detectors." ); + + const Trk::TrackingVolume* detectorWithBp = + m_trackingVolumeCreator->createContainerTrackingVolume(idVolumes, + *m_materialProperties, + volumeName, + m_buildBoundaryLayers, + m_replaceJointBoundaries); + + // if packing is needed ------------------------------------------------------------------ + const Trk::TrackingVolume* highestIdVolume = 0; + if (enclose){ + + // negative positions + std::vector<double> negDiscPositionZ(m_enclosingDiscPositionZ); + for (std::vector<double>::iterator posIter = negDiscPositionZ.begin(); + posIter != negDiscPositionZ.end(); ++posIter) (*posIter) *= -1; + + + const Trk::TrackingVolume* negativeEnclosure = negDiscPositionZ.size() ? + m_trackingVolumeCreator->createGapTrackingVolume(*m_materialProperties, + 0., enclosingVolumeRadius, + -enclosingVolumeHalfZ, -overallExtendZ, + negDiscPositionZ, false, + m_namespace+"Gaps::NegativeEnclosure") : + m_trackingVolumeCreator->createGapTrackingVolume(*m_materialProperties, + 0., enclosingVolumeRadius, + -enclosingVolumeHalfZ, -overallExtendZ, + 1, false, + m_namespace+"Gaps::NegativeEnclosure"); + + const Trk::TrackingVolume* positiveEnclosure = m_enclosingDiscPositionZ.size() ? + m_trackingVolumeCreator->createGapTrackingVolume(*m_materialProperties, + 0., enclosingVolumeRadius, + overallExtendZ, enclosingVolumeHalfZ, + m_enclosingDiscPositionZ, false, + m_namespace+"Gaps::PositiveEnclosure") : + m_trackingVolumeCreator->createGapTrackingVolume(*m_materialProperties, + 0., enclosingVolumeRadius, + overallExtendZ,enclosingVolumeHalfZ, + 1, false, + m_namespace+"Gaps::PositiveEnclosure"); + + std::vector<const Trk::TrackingVolume*> enclosedVolumes; + enclosedVolumes.push_back(negativeEnclosure); + enclosedVolumes.push_back(detectorWithBp); + enclosedVolumes.push_back(positiveEnclosure); + + const Trk::TrackingVolume* enclosedDetector = + m_trackingVolumeCreator->createContainerTrackingVolume(enclosedVolumes, + *m_materialProperties, + m_exitVolume, + m_buildBoundaryLayers, + m_replaceJointBoundaries); + + highestIdVolume = enclosedDetector; + } else + highestIdVolume = detectorWithBp; + + // (V) create the TrackingGeometry ------------------------------------------------------ + trackingGeometry = new Trk::TrackingGeometry(highestIdVolume); + + if (m_indexStaticLayers) { + ATH_MSG_VERBOSE("Re-index the static layers ..."); + // ST temporary hack till layer numbering resolved + //trackingGeometry->indexStaticLayers(geometrySignature()); + trackingGeometry->indexStaticLayers(Trk::Global); + } + + + return std::make_pair(range, trackingGeometry); +} + +// finalize +StatusCode InDet::RobustTrackingGeometryBuilderCond::finalize() +{ + ATH_MSG_INFO( "finalize() successful" ); + return StatusCode::SUCCESS; +} + + +const Trk::TrackingVolume* InDet::RobustTrackingGeometryBuilderCond::packVolumeTriple( + const std::vector<const Trk::Layer*>& negLayers, + const std::vector<const Trk::Layer*>& centralLayers, + const std::vector<const Trk::Layer*>& posLayers, + double rMin, double rMax, + double zMax, double zPosCentral, + const std::string& baseName, + int colorCode, + Trk::BinningType bintyp) const +{ + + + ATH_MSG_VERBOSE( '\t' << '\t'<< "Pack provided Layers from '" << baseName << "' triple into a container volume. " ); + + // create the strings + std::string volumeBase = m_namespace+"Detectors::"+baseName; + + const Trk::TrackingVolume* negativeVolume = + m_trackingVolumeCreator->createTrackingVolume(negLayers, + *m_materialProperties, + rMin,rMax, + -zMax,-zPosCentral, + volumeBase+"::NegativeEndcap", + bintyp); + + const Trk::TrackingVolume* centralVolume = + m_trackingVolumeCreator->createTrackingVolume(centralLayers, + *m_materialProperties, + rMin,rMax, + -zPosCentral,zPosCentral, + volumeBase+"::Barrel", + bintyp); + + const Trk::TrackingVolume* positiveVolume = + m_trackingVolumeCreator->createTrackingVolume(posLayers, + *m_materialProperties, + rMin,rMax, + zPosCentral,zMax, + volumeBase+"::PositiveEndcap", + bintyp); + + // the base volumes have been created + ATH_MSG_VERBOSE('\t' << '\t'<< "Volumes have been created, now pack them into a triple."); + // registerColorCode + negativeVolume->registerColorCode(colorCode); + centralVolume->registerColorCode(colorCode); + positiveVolume->registerColorCode(colorCode); + + // pack them together + std::vector<const Trk::TrackingVolume*> tripleVolumes; + tripleVolumes.push_back(negativeVolume); + tripleVolumes.push_back(centralVolume); + tripleVolumes.push_back(positiveVolume); + + // create the tiple container + const Trk::TrackingVolume* tripleContainer = + m_trackingVolumeCreator->createContainerTrackingVolume(tripleVolumes, + *m_materialProperties, + volumeBase, + m_buildBoundaryLayers, + m_replaceJointBoundaries); + + ATH_MSG_VERBOSE( '\t' << '\t'<< "Created container volume with bounds: " << tripleContainer->volumeBounds() ); + + return tripleContainer; +} + +const Trk::TrackingVolume* InDet::RobustTrackingGeometryBuilderCond::packVolumeTriple( + const std::vector<const Trk::TrackingVolume*>& negVolumes, + const std::vector<const Trk::TrackingVolume*>& centralVolumes, + const std::vector<const Trk::TrackingVolume*>& posVolumes, + const std::string& baseName) const +{ + ATH_MSG_VERBOSE( '\t' << '\t'<< "Pack provided Volumes from '" << baseName << "' triple into a container volume. " ); + + unsigned int negVolSize = negVolumes.size(); + unsigned int cenVolSize = centralVolumes.size(); + unsigned int posVolSize = posVolumes.size(); + + + + // create the strings + std::string volumeBase = m_namespace+"Containers::"+baseName; + + const Trk::TrackingVolume* negativeVolume = (negVolSize > 1) ? + m_trackingVolumeCreator->createContainerTrackingVolume(negVolumes, + *m_materialProperties, + volumeBase+"::NegativeSector", + m_buildBoundaryLayers, + m_replaceJointBoundaries) : + (negVolSize ? negVolumes[0] : 0); + const Trk::TrackingVolume* centralVolume = (cenVolSize > 1) ? + m_trackingVolumeCreator->createContainerTrackingVolume(centralVolumes, + *m_materialProperties, + volumeBase+"::CentralSector", + m_buildBoundaryLayers, + m_replaceJointBoundaries) : + (cenVolSize ? centralVolumes[0] : 0) ; + + const Trk::TrackingVolume* positiveVolume = ( posVolSize > 1) ? + m_trackingVolumeCreator->createContainerTrackingVolume(posVolumes, + *m_materialProperties, + volumeBase+"::PositiveSector", + m_buildBoundaryLayers, + m_replaceJointBoundaries) : + (posVolSize ? posVolumes[0] : 0); + + if (!negativeVolume && !positiveVolume){ + ATH_MSG_DEBUG( "No negative/positive sector given - no packing needed, returning central container!" ); + return centralVolume; + } + // pack them together + std::vector<const Trk::TrackingVolume*> tripleVolumes; + if (negativeVolume) tripleVolumes.push_back(negativeVolume); + if (centralVolume) tripleVolumes.push_back(centralVolume); + if (positiveVolume) tripleVolumes.push_back(positiveVolume); + // create the tiple container + const Trk::TrackingVolume* tripleContainer = + m_trackingVolumeCreator->createContainerTrackingVolume(tripleVolumes, + *m_materialProperties, + volumeBase, + m_buildBoundaryLayers, + m_replaceJointBoundaries); + return tripleContainer; +} diff --git a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/SiLayerBuilderCond.cxx b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/SiLayerBuilderCond.cxx new file mode 100755 index 00000000000..6aadedafbdf --- /dev/null +++ b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/SiLayerBuilderCond.cxx @@ -0,0 +1,1178 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// SiLayerBuilderCond.cxx, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#include "InDetTrackingGeometry/SiLayerBuilderCond.h" +#include "InDetTrackingGeometry/PixelOverlapDescriptor.h" +#include "InDetTrackingGeometry/SCT_OverlapDescriptor.h" +#include "InDetTrackingGeometry/DiscOverlapDescriptor.h" +//InDet include +#include "PixelReadoutGeometry/PixelDetectorManager.h" +#include "SCT_ReadoutGeometry/SCT_DetectorManager.h" +#include "InDetReadoutGeometry/SiDetectorElement.h" +#include "InDetReadoutGeometry/SiDetectorElementCollection.h" +#include "InDetIdentifier/SCT_ID.h" +#include "InDetIdentifier/PixelID.h" +// Trk inlcude +#include "TrkDetDescrUtils/BinUtility.h" +#include "TrkDetDescrUtils/BinnedArray1D1D.h" +#include "TrkDetDescrUtils/BinnedArray2D.h" +#include "TrkDetDescrUtils/BinnedArray1D.h" +#include "TrkDetDescrUtils/GeometryStatics.h" +#include "TrkGeometry/LayerMaterialProperties.h" +#include "TrkGeometry/BinnedLayerMaterial.h" +#include "TrkGeometry/HomogeneousLayerMaterial.h" +#include "TrkGeometry/MaterialProperties.h" +#include "TrkGeometry/CylinderLayer.h" +#include "TrkGeometry/DiscLayer.h" +#include "TrkGeometry/PlaneLayer.h" +#include "TrkSurfaces/Surface.h" +#include "TrkSurfaces/CylinderBounds.h" +#include "TrkSurfaces/DiscBounds.h" +// GeoModel +#include "GeoModelKernel/GeoLogVol.h" +#include "GeoModelKernel/GeoVFullPhysVol.h" +#include "GeoModelKernel/GeoMaterial.h" +// Gaudi +#include "GaudiKernel/ISvcLocator.h" +#include "GaudiKernel/SystemOfUnits.h" +#include "GaudiKernel/SmartDataPtr.h" +// STL +#include <map> + +std::vector<const Trk::CylinderLayer*> InDet::SiLayerBuilderCond::s_splitCylinderLayers; +std::vector<const Trk::DiscLayer*> InDet::SiLayerBuilderCond::s_splitDiscLayers; +EventIDRange InDet::SiLayerBuilderCond::s_splitIOVRange; +double InDet::SiLayerBuilderCond::s_splitRadius = 0.; + +// constructor +InDet::SiLayerBuilderCond::SiLayerBuilderCond(const std::string& t, const std::string& n, const IInterface* p) : + AthAlgTool(t,n,p), + m_pixelCase(true), + m_siMgr(0), + m_siMgrLocation("Pixel"), + m_pixIdHelper(0), + m_sctIdHelper(0), + m_setLayerAssociation(true), + m_barrelLayerBinsZ(100), + m_barrelLayerBinsPhi(1), + m_barrelEnvelope(0.1), + m_barrelEdbTolerance(0.05), + m_endcapRingLayout(false), + m_endcapLayerBinsR(100), + m_endcapLayerBinsPhi(1), + m_endcapEnvelope(0.1), + m_endcapComplexRingBinning(true), + m_identification("Pixel"), + m_splitMode(0), + m_splitTolerance(10.), + m_runGeometryValidation(true) +{ + declareInterface<Trk::ILayerBuilderCond>(this); + // general steering + declareProperty("PixelCase" , m_pixelCase); + declareProperty("SiDetManagerLocation" , m_siMgrLocation); + declareProperty("SetLayerAssociation" , m_setLayerAssociation); + // For the Active Barrel Material + declareProperty("BarrelAdditionalLayerRadii" , m_barrelAdditionalLayerR); + declareProperty("BarrelAdditionalLayerType" , m_barrelAdditionalLayerType); + declareProperty("BarrelLayerBinsZ" , m_barrelLayerBinsZ); + declareProperty("BarrelLayerBinsPhi" , m_barrelLayerBinsPhi); + declareProperty("BarrelEnvelope" , m_barrelEnvelope); + declareProperty("BarrelEdbTolerance" , m_barrelEdbTolerance); + // For the Active Endcap Material + declareProperty("EndcapRingLayout" , m_endcapRingLayout); + declareProperty("EndcapAdditionalLayerPositionsZ" , m_endcapAdditionalLayerPosZ); + declareProperty("EndcapAdditionalLayerType" , m_endcapAdditionalLayerType); + declareProperty("EndcapLayerBinsR" , m_endcapLayerBinsR); + declareProperty("EndcapLayerBinsPhi" , m_endcapLayerBinsPhi); + declareProperty("EndcapEnvelope" , m_endcapEnvelope); + declareProperty("EndcapComplexRingBinning" , m_endcapComplexRingBinning); + // identification + declareProperty("Identification" , m_identification); + // split mode for multiple pixel systems (upgrade) + declareProperty("SplitMode" , m_splitMode); + declareProperty("SplitTolerance" , m_splitTolerance); + // Validation + declareProperty("GeometryValidation" , m_runGeometryValidation); +} + +// destructor +InDet::SiLayerBuilderCond::~SiLayerBuilderCond() +{} + +// Athena standard methods +// initialize +StatusCode InDet::SiLayerBuilderCond::initialize() +{ + + ATH_MSG_DEBUG( "initialize()" ); + // get Pixel Detector Description Manager + if (m_pixelCase){ + const InDetDD::PixelDetectorManager* pixMgr = 0; + if ((detStore()->retrieve(pixMgr, m_siMgrLocation)).isFailure()) { + ATH_MSG_ERROR( "Could not get PixelDetectorManager '" << m_siMgrLocation << "', no layers for Pixel Detector will be built. " ); + } else { + ATH_MSG_VERBOSE( "PixelDetectorManager retrieved with key '" << m_siMgrLocation <<"'." ); + // assign the detector manager to the silicon manager + m_siMgr = pixMgr; + if (detStore()->retrieve(m_pixIdHelper, "PixelID").isFailure()) + ATH_MSG_ERROR("Could not get Pixel ID helper"); + } + ATH_CHECK(m_PixelReadKey.initialize()); + } else { + const InDetDD::SCT_DetectorManager* sctMgr = 0; + if ((detStore()->retrieve(sctMgr, m_siMgrLocation)).isFailure()) { + ATH_MSG_ERROR( "Could not get SCT_DetectorManager '" << m_siMgrLocation << "', no layers for SCT Detector will be built. " ); + } else { + ATH_MSG_VERBOSE( "SCT_DetectorManager retrieved with key '" << m_siMgrLocation <<"'." ); + // assign the detector manager to the silicon manager + m_siMgr = sctMgr; + if (detStore()->retrieve(m_sctIdHelper, "SCT_ID").isFailure()) + ATH_MSG_ERROR("Could not get SCT ID helper"); + } + + ATH_CHECK(m_SCT_ReadKey.initialize()); + ATH_CHECK(m_PixelReadKey.initialize()); + + } + return StatusCode::SUCCESS; +} + +// finalize +StatusCode InDet::SiLayerBuilderCond::finalize() +{ + ATH_MSG_DEBUG( "finalize() successful" ); + return StatusCode::SUCCESS; +} + + +/** LayerBuilder interface method - returning Barrel-like layers */ +std::pair<EventIDRange, const std::vector<const Trk::CylinderLayer*>*> InDet::SiLayerBuilderCond::cylindricalLayers(const EventContext& ctx) const +{ + + // split mode 2nd part return the already built layers + if (m_splitMode && s_splitCylinderLayers.size() ){ + ATH_MSG_DEBUG( "[ Split mode/ Part 2 ] Returning " << s_splitCylinderLayers.size() << " cylinder layers." ); + ATH_MSG_VERBOSE( " Split radius was set to " << s_splitRadius ); + std::vector<const Trk::CylinderLayer*>* splitCylinderLayers = dressCylinderLayers(s_splitCylinderLayers); + s_splitCylinderLayers.clear(); + return std::make_pair(s_splitIOVRange, splitCylinderLayers); + } else if (m_splitMode){ + ATH_MSG_DEBUG( "[ Split mode/ Part 1 ] Initializing." ); + s_splitRadius = m_splitMode < 0 ? 10e10 : 0.; + } + + + // sanity check for ID Helper + if (!m_pixIdHelper && !m_sctIdHelper){ + ATH_MSG_ERROR("Neither Pixel nor SCT Detector Manager or ID Helper could be retrieved - giving up."); + //create dummy infinite range + EventIDRange range; + return std::pair<EventIDRange, const std::vector<const Trk::CylinderLayer*>*>(range,nullptr); + } + + // take the numerlogoy + const InDetDD::SiNumerology& siNumerology = m_siMgr->numerology(); + + // pre-set parameters for the run + size_t barrelLayers = 0; + // save way to estimate the number of barrel layers : they can be deactivated hence the useLayer(i) check + for (int i = 0; i < siNumerology.numLayers(); i++) + if (siNumerology.useLayer(i)) barrelLayers++; + + + // screen output + ATH_MSG_DEBUG( "Configured to build " << barrelLayers << " (active) barrel layers (out of " << siNumerology.numLayers() << " )" ); + if (m_barrelAdditionalLayerR.size()) + ATH_MSG_DEBUG( "Additionally " << m_barrelAdditionalLayerR.size() << " material layers will be built."); + + // split mode for SLHC setup + if (m_splitMode) + ATH_MSG_DEBUG( "[ Split mode ] Some layers may be cached." ); + + // for barrels (the statistics for ordering the modules) + std::vector<double> layerRadius(barrelLayers,0.); + std::vector<double> layerRmin(barrelLayers,10e10); + std::vector<double> layerRmax(barrelLayers,0.); + std::vector<double> layerThickness(barrelLayers,0.); + std::vector<double> layerMinZ(barrelLayers,0.); + std::vector<double> layerMaxZ(barrelLayers,0.); + std::vector<double> layerHalfLength(barrelLayers,0.); + std::vector<double> layerMinPhi(barrelLayers,0.); + std::vector<double> layerMaxPhi(barrelLayers,0.); + std::vector<size_t> layerPhiSectors(barrelLayers,0); + std::vector<size_t> layerZsectors(barrelLayers,0); + std::vector< std::vector<float> > layerZboundaries(barrelLayers, std::vector<float>()); + std::vector< std::vector< Trk::SurfaceOrderPosition > > layerSurfaces(barrelLayers, std::vector< Trk::SurfaceOrderPosition >()); + + // cache needed + double minHalflengthZ = 10e10; + double maxHalflengthZ = 0; + size_t sumCheckBarrelModules = 0; + size_t barrelModules = 0; + + // [-A-] ------------------------ LOOP over Detector Elements of sensitive layers ----------------------------------- + // iterate over the detector elements for layer dimension, etc. + SG::ReadCondHandle<InDetDD::SiDetectorElementCollection>* readHandle; + if(m_pixelCase){ + readHandle = new SG::ReadCondHandle<InDetDD::SiDetectorElementCollection> (m_PixelReadKey, ctx); + }else{ + readHandle = new SG::ReadCondHandle<InDetDD::SiDetectorElementCollection> (m_SCT_ReadKey, ctx); + } + const InDetDD::SiDetectorElementCollection* readCdo{**readHandle}; + InDetDD::SiDetectorElementCollection::const_iterator sidetIter = readCdo->begin(); + for (; sidetIter != readCdo->end(); sidetIter++){ + // Barrel check + if ((*sidetIter) && (*sidetIter)->isBarrel()){ + // unit test + ++barrelModules; + // get the identifier + Identifier currentId((*sidetIter)->identify()); + int currentlayer = m_pixIdHelper ? m_pixIdHelper->layer_disk(currentId) : m_sctIdHelper->layer_disk(currentId); + //skip the layer if it is chosen to be switched off + if ( !m_siMgr->numerology().useLayer(currentlayer) ) continue; + // (A) Determination of phi / eta sectors --------------------------------------------------- + // only do the exercise if it hasn't been done already + if (layerPhiSectors[currentlayer] == 0){ + ATH_MSG_VERBOSE("Pre-processing Elements from Layer (id from idHelper): " << currentlayer ); + // set number of phiSectors + layerPhiSectors[currentlayer] = m_siMgr->numerology().numPhiModulesForLayer(currentlayer); + // set number of etaSectors + layerZsectors[currentlayer] = m_siMgr->numerology().numEtaModulesForLayer(currentlayer); + // get the HalfLength of the Layer + const InDetDD::SiDetectorElement* countPtr = (*sidetIter); + // needed for the complex z binning if activated + double lastModuleZ = 0.; + std::vector<float> zboundaries; + zboundaries.reserve(layerZsectors[currentlayer]+1); + // walk all along to negative eta + while ((countPtr->prevInEta())) + countPtr = countPtr->prevInEta(); + layerMinZ[currentlayer] = countPtr->center().z() - 0.5*fabs(countPtr->length()); + zboundaries.push_back(layerMinZ[currentlayer]); + lastModuleZ = countPtr->center().z(); + // register the layer minZ into the zboundaries + // now walk all along to positive eta + while ((countPtr->nextInEta())) { + countPtr = countPtr->nextInEta(); + // for complex binning + double currentModuleZ = countPtr->center().z(); + double currentZboundary = 0.5*(lastModuleZ+currentModuleZ); + zboundaries.push_back(currentZboundary); + lastModuleZ = currentModuleZ; + } + layerMaxZ[currentlayer] = fabs(countPtr->center().z()) + 0.5*fabs(countPtr->length()); + zboundaries.push_back(layerMaxZ[currentlayer]); + + // complex z binning mode + layerZboundaries[currentlayer] = zboundaries; + // chose which one to register for the split mode (SLHC) + layerHalfLength[currentlayer] = layerMinZ[currentlayer]*layerMinZ[currentlayer] > layerMaxZ[currentlayer]*layerMaxZ[currentlayer] ? + fabs(layerMinZ[currentlayer]) : layerMaxZ[currentlayer]; + // get the haflength of the layer + takeSmaller( minHalflengthZ, layerHalfLength[currentlayer]); + takeBigger( maxHalflengthZ, layerHalfLength[currentlayer]); + ATH_MSG_VERBOSE(" -> Determined Layer z range with : " << layerMinZ[currentlayer] << " / " << layerMaxZ[currentlayer] ); + ATH_MSG_VERBOSE(" -> Symmetric half length taken : " << layerHalfLength[currentlayer]); + } + + // (B) Determination of the radius ------------------------------------------------ + // getting inner module + const InDetDD::SiDetectorElement* otherSide = (*sidetIter)->otherSide(); + // take the maximum layer radius + double currentR = (*sidetIter)->center().perp(); + double currentRmax = (*sidetIter)->rMax(); + double currentRmin = (*sidetIter)->rMin(); + layerRadius[currentlayer] = (currentR > layerRadius[currentlayer]) ? currentR : layerRadius[currentlayer]; + if (otherSide){ + takeBigger( currentRmax, (otherSide)->rMax() ); + takeSmaller( currentRmin, (otherSide)->rMin() ); + } + takeSmaller( layerRmin[currentlayer], currentRmin ); + takeBigger( layerRmax[currentlayer], currentRmax ); + + // handle the split mode + if (m_splitMode > 0) takeBigger(s_splitRadius, layerRadius[currentlayer]); + else if (m_splitMode < 0) takeSmaller (s_splitRadius, layerRadius[currentlayer]); + + // fill the Surface vector + Amg::Vector3D orderPosition((*sidetIter)->center()); + double currentPhi = orderPosition.phi(); + takeSmaller( layerMinPhi[currentlayer], currentPhi); + takeBigger( layerMaxPhi[currentlayer], currentPhi); + + // decide which one to register on the Radius: always the one with smaller radius + bool takeIt = (!otherSide || (*sidetIter)->center().perp() < otherSide->center().perp() ); + const Trk::Surface* moduleSurface = takeIt ? (&((*sidetIter)->surface())) : (&(otherSide->surface())); + + // register the module surface + Trk::SharedObject<const Trk::Surface> sharedSurface(moduleSurface, Trk::do_not_delete<const Trk::Surface>); + + Trk::SurfaceOrderPosition surfaceOrder(sharedSurface, orderPosition); + if (takeIt) (layerSurfaces[currentlayer]).push_back(surfaceOrder); + + } else if (!(*sidetIter)) // barrel chek and screen output + ATH_MSG_WARNING("NULL pointer to Barrel module given by SiDetectorManager! Please check db & dict.xml"); + + } // SiDet Loop + + // --------------------------- enf of LOOP over Detector Elements of sensitive layers ---------------------------------- + + // [-B-] ------------------------ Construction of the layers ----------------------------------- + // [-B-1] construct the detection layers + std::vector< const Trk::CylinderLayer* > cylinderDetectionLayers; + int layerCounter = 0; + double currentLayerExtend = 0.; + + // construct detection layers + for (auto& layerRadiusIter : layerRadius) { + + Trk::CylinderLayer* activeLayer = 0; + double currentLayerRadius = 10e10; + bool splitDone = false; + // non-equidistant binning used ? auto-detection + bool nonEquidistantBinning = false; + { + // calculate the average bin size + const double averageBinSize = (layerMaxZ[layerCounter]-layerMinZ[layerCounter])/(layerZsectors[layerCounter]); + const double inv_averageBinSize2 = 1. / (averageBinSize*averageBinSize); + // loop over the boundaries and check if theyare outside the tolerance + auto bIter = layerZboundaries[layerCounter].begin(); + auto bIterE = layerZboundaries[layerCounter].end(); + for ( ++bIter; bIter != bIterE; ++bIter ){ + float cZ = (*bIter); + float pZ = (*(bIter-1)); + nonEquidistantBinning = (cZ-pZ)*(cZ-pZ)*inv_averageBinSize2 < (1.-m_barrelEdbTolerance) *(1.-m_barrelEdbTolerance); + if (nonEquidistantBinning){ + ATH_MSG_VERBOSE("Non-equidistant binning for (Silicon) Surfaces on this layer with radius " << layerRadiusIter << " detected. "); + ATH_MSG_VERBOSE("Difference " << (cZ-pZ)/averageBinSize << " at a allowed tolerance of : " << m_barrelEdbTolerance ); + break; + } + } + } + + //(1) the detecting layer : sensitive modules -------------------------------------------------------------------- + // create the BinKeyUtility - the phi binning is identical + double halfPhiStep = M_PI/layerPhiSectors[layerCounter]; + // protection in case phi value was fluctuating around 0 or M_PI in parsing + if (fabs(layerMinPhi[layerCounter]+layerMaxPhi[layerCounter])< halfPhiStep && fabs(M_PI+layerMinPhi[layerCounter]) < 0.5*halfPhiStep ){ + ATH_MSG_VERBOSE("Detected module fluctuation around +/- M_PI, correcting for it."); + ATH_MSG_VERBOSE(" min phi / max phi detected : " << layerMinPhi[layerCounter] << " / " << layerMaxPhi[layerCounter] ); + layerMinPhi[layerCounter] += 2*halfPhiStep; + } + // now prepare the phi values + ATH_MSG_VERBOSE("Preparing the Phi-binning for : " << layerPhiSectors[layerCounter] << " sectors."); + ATH_MSG_VERBOSE(" min phi / max phi detected : " << layerMinPhi[layerCounter] << " / " << layerMaxPhi[layerCounter] ); + double minPhiCorrected = layerMinPhi[layerCounter]-halfPhiStep; + double maxPhiCorrected = layerMaxPhi[layerCounter]+halfPhiStep; + // catch if the minPhi falls below M_PI + if (minPhiCorrected < -M_PI){ + minPhiCorrected += 2*halfPhiStep; + maxPhiCorrected += 2*halfPhiStep; + } + ATH_MSG_VERBOSE(" min phi / max phi corrected : " << minPhiCorrected << " / " << maxPhiCorrected ); + + + Trk::BinUtility* currentBinUtility = new Trk::BinUtility(layerPhiSectors[layerCounter], + minPhiCorrected, + maxPhiCorrected, + Trk::closed, Trk::binPhi); + if (nonEquidistantBinning) + (*currentBinUtility) += Trk::BinUtility(layerZboundaries[layerCounter], + Trk::open, + Trk::binZ); + else + (*currentBinUtility) += Trk::BinUtility(layerZsectors[layerCounter], + layerMinZ[layerCounter], + layerMaxZ[layerCounter], + Trk::open, + Trk::binZ); + // creating the binned array output + ATH_MSG_VERBOSE("Creating the binned array for the sensitive detector elements with BinUtility :"); + ATH_MSG_VERBOSE( *currentBinUtility ); + // the binned array for the senstive surfaces to be built + Trk::BinnedArray<Trk::Surface>* currentBinnedArray = + new Trk::BinnedArray2D<Trk::Surface>(layerSurfaces[layerCounter],currentBinUtility); + // unit test for sub surface ordering + const std::vector<const Trk::Surface*>& arraySurfaces = currentBinnedArray->arrayObjects(); + + if (m_runGeometryValidation){ + // checking for : + // - empty surface bins + // - doubly filled bins + std::map< const Trk::Surface*,Amg::Vector3D > uniqueSurfaceMap; + auto usmIter = uniqueSurfaceMap.end(); + // ------- iterate + auto asurfIter = arraySurfaces.begin(); + auto asurfIterEnd = arraySurfaces.end(); + for ( ; asurfIter != asurfIterEnd; ++asurfIter){ + if ( (*asurfIter) ) { + ++sumCheckBarrelModules; + usmIter = uniqueSurfaceMap.find(*asurfIter); + if ( usmIter != uniqueSurfaceMap.end() ) + ATH_MSG_WARNING("Non-unique surface found with eta/phi = " << (*asurfIter)->center().eta() << " / " << (*asurfIter)->center().phi()); + else uniqueSurfaceMap[(*asurfIter)] = (*asurfIter)->center(); + } + else + ATH_MSG_WARNING("Null surface defined in BinUtility ArraySurfaces vector"); + } + } + + // dynamic layer extend and splitDone check (split mode need the dynamic extend !) + currentLayerExtend = layerHalfLength[layerCounter]; + + // check if split has been done + // split mode < 0 : compare to maxHalfLength + // split mode > 0 : compare to minHalflength + double compareHalfLengthZ = m_splitMode < 0 ? maxHalflengthZ : minHalflengthZ; + + splitDone = m_splitMode && fabs(layerHalfLength[layerCounter]-compareHalfLengthZ) > m_splitTolerance; + if (m_splitMode){ + ATH_MSG_DEBUG( "[ Split mode / part 1 ] Layer Halflength determined as: " << layerHalfLength[layerCounter]); + ATH_MSG_DEBUG( " while minHalflengthZ is: " << minHalflengthZ ); + ATH_MSG_DEBUG( " -> consequence is: " << (splitDone ? "store for iteration 2" : "build") ); + } + + // dynamic layer extend determined by the sensitive layer dimensions + layerRadius[layerCounter] = 0.5*(layerRmax[layerCounter] + layerRmin[layerCounter]); + layerThickness[layerCounter] = layerRmax[layerCounter] - layerRmin[layerCounter]; + + // create the material + const Trk::LayerMaterialProperties* layerMaterial = barrelLayerMaterial(layerRadius[layerCounter], currentLayerExtend); + double currentLayerThickness = layerThickness[layerCounter]+m_barrelEnvelope; + + // screen output + ATH_MSG_DEBUG( "Construct BinnedArray for CylinderLayer with "<< (layerSurfaces[layerCounter]).size() << " SubSurfaces." ); + ATH_MSG_DEBUG( "Building a CylinderLayer with " << layerPhiSectors[layerCounter] + << " / " << ( nonEquidistantBinning ? layerZboundaries[layerCounter].size() : layerZsectors[layerCounter] ) << " phi/z bins. " ); + ATH_MSG_DEBUG( " -> With Radius : " << layerRadius[layerCounter] ); + ATH_MSG_DEBUG( " -> With Thickness : " << currentLayerThickness << " - includes envelope tolerance : " << m_barrelEnvelope ); + ATH_MSG_DEBUG( " -> With Zmin/Zmax : " << -currentLayerExtend << " / " << currentLayerExtend ); + + if ( nonEquidistantBinning && layerZboundaries[layerCounter].size() ){ + // overrule the min bin - with the min radius + // do the output to screen + double currentZ = -currentLayerExtend; + msg(MSG::DEBUG) << " -> Z binning at : "; + for (size_t zbin = 0; zbin < layerZboundaries[layerCounter].size(); ++zbin) { + currentZ += layerZboundaries[layerCounter][zbin]; + msg(MSG::DEBUG) << currentZ; + if (zbin < layerZboundaries[layerCounter].size()-1) + msg(MSG::DEBUG) << ", "; + } + msg(MSG::DEBUG) << endmsg; + } + // prepare the right overlap descriptor + Trk::OverlapDescriptor* olDescriptor = 0; + if (m_pixelCase) + olDescriptor = new InDet::PixelOverlapDescriptor; + else olDescriptor = new InDet::SCT_OverlapDescriptor; + // for eventual use with the passive layer + currentLayerRadius = layerRadius[layerCounter]; + + // construct the layer (finally) + activeLayer = new Trk::CylinderLayer(new Trk::CylinderBounds(layerRadius[layerCounter],currentLayerExtend), + currentBinnedArray, + *layerMaterial, + layerThickness[layerCounter], + olDescriptor); + // cleanup of the layer material -------------------------------------------------------------- + delete layerMaterial; + // register the layer to the surfaces + const std::vector<const Trk::Surface*>& layerSurfaces = currentBinnedArray->arrayObjects(); + registerSurfacesToLayer(layerSurfaces,*activeLayer); + + // (3) register the layers --- either in the split vector or in the return vector + if (splitDone) { + ATH_MSG_DEBUG( "[ Split mode / Part 1 ] Layer cached for Part 2" ); + readHandle->range(s_splitIOVRange); + if (activeLayer) s_splitCylinderLayers.push_back(activeLayer); + // get the split radius to the smallest one possible + if (m_splitMode > 0) takeSmaller( s_splitRadius, currentLayerRadius); + ATH_MSG_DEBUG("[ Split mode / part 1 ] Split radius (temproarily) set to : " << s_splitRadius ); + } else { + if (m_splitMode < 0) takeBigger ( s_splitRadius, currentLayerRadius ); + if (activeLayer) cylinderDetectionLayers.push_back(activeLayer); + } + // increase the layer counter --- it is built + ++layerCounter; + + } // layer construction + // --------------------------- enf of detection layer construction loop ---------------------------------- + + ATH_MSG_DEBUG("Creating the final CylinderLayer collection with (potentially) additional layers."); + std::vector< const Trk::CylinderLayer* >* cylinderLayers = dressCylinderLayers(cylinderDetectionLayers); + + // multiply the check number in case of SCT + sumCheckBarrelModules *= (m_pixelCase) ? 1 : 2; + ATH_MSG_DEBUG( barrelModules << " Barrel Modules parsed for Cylinder Layer dimenstions." ); + ATH_MSG_DEBUG( sumCheckBarrelModules << " Barrel Modules filled in Cylinder Layer Arrays." ); + if ( barrelModules-sumCheckBarrelModules ) + ATH_MSG_WARNING( barrelModules-sumCheckBarrelModules << " Modules not registered properly in binned array." ); + + if (m_splitMode) + ATH_MSG_DEBUG("[ Split mode / part 1 ] Split radius determined as : " << s_splitRadius ); + + ATH_MSG_DEBUG("Returning " << cylinderLayers->size() << " cylinder layers."); + EventIDRange range; + readHandle->range(range); + delete readHandle; + std::pair<EventIDRange, const std::vector<const Trk::CylinderLayer*>*> cylinderLayersPair = std::make_pair(range,cylinderLayers); + return cylinderLayersPair; +} + +/** LayerBuilder interface method - returning Endcap-like layers */ +std::pair<EventIDRange, const std::vector<const Trk::DiscLayer*>*> InDet::SiLayerBuilderCond::discLayers(const EventContext& ctx) const +{ + + // TODO: remove s_splitDiscLayers cache to make threadsafe. ignored for now as is only for ITk + // split mode 2nd + if (m_splitMode && s_splitDiscLayers.size() ){ + ATH_MSG_DEBUG( "[ Split mode/ Part 2 ] Returning " << s_splitDiscLayers.size() << " disc layers." ); + std::vector<const Trk::DiscLayer*>* splitDiscs = new std::vector<const Trk::DiscLayer*>(s_splitDiscLayers); + s_splitDiscLayers.clear(); + return std::make_pair(s_splitIOVRange, splitDiscs); + } + // sanity check for ID Helper + if (!m_pixIdHelper && !m_sctIdHelper){ + ATH_MSG_ERROR("Neither Pixel nor SCT Detector Manager or ID Helper could be retrieved - giving up."); + //create dummy infinite range + EventIDRange range; + return std::pair<EventIDRange, const std::vector<const Trk::DiscLayer*>*>(range,nullptr); + } + + // check for DBMS + int nDBMLayers = m_siMgr->numerology().numEndcapsDBM(); + if (!nDBMLayers) return createDiscLayers(ctx); + + ATH_MSG_DEBUG( "Found " << m_siMgr->numerology().numEndcapsDBM() << " DBM layers active, building first ECs, then DBMS"); + std::pair<EventIDRange, std::vector<const Trk::DiscLayer*>*> ecLayers = createDiscLayers(ctx); + if (ecLayers.second) { + ATH_MSG_VERBOSE( "Created " << ecLayers.second->size() << " endcap layers w/o DBM."); + ecLayers = createDiscLayers(ctx, ecLayers.second); + ATH_MSG_VERBOSE( "Created " << ecLayers.second->size() << " endcap layers with DBM."); + } + return ecLayers; + +} + +/** LayerBuilder interface method - returning Endcap-like layers */ +std::pair<EventIDRange, std::vector< const Trk::DiscLayer* >* > InDet::SiLayerBuilderCond::createDiscLayers(const EventContext& ctx, std::vector<const Trk::DiscLayer*>* dLayers) const { + + // this is the DBM flag + bool isDBM = (dLayers!=NULL); + + // get general layout + SG::ReadCondHandle<InDetDD::SiDetectorElementCollection>* readHandle; + if(m_pixelCase){ + readHandle = new SG::ReadCondHandle<InDetDD::SiDetectorElementCollection> (m_PixelReadKey, ctx); + }else{ + readHandle = new SG::ReadCondHandle<InDetDD::SiDetectorElementCollection> (m_SCT_ReadKey, ctx); + } + const InDetDD::SiDetectorElementCollection* readCdo{**readHandle}; + InDetDD::SiDetectorElementCollection::const_iterator sidetIter = readCdo->begin(); + + // save way to estimate the number of barrels + unsigned int endcapLayers = 0; + if (isDBM){ + endcapLayers = m_siMgr->numerology().numDisksDBM(); + ATH_MSG_DEBUG( "Configured to build " << endcapLayers << "*2 disc-like DBM layers" ); + } else { + for (int i = 0; i < m_siMgr->numerology().numDisks(); i++) + if (m_siMgr->numerology().useDisk(i)) endcapLayers++; + ATH_MSG_DEBUG( "Configured to build " << endcapLayers << " *2 disc-like layers (+ additional support layers)." ); + } + + if (m_splitMode) + ATH_MSG_DEBUG( "[ Split mode ] Some layers may bee cached." ); + + // prepare the vectors + std::vector<double> discZmin(2*endcapLayers,10e10); + std::vector<double> discZmax(2*endcapLayers,-10e10); + std::vector<double> discZpos(2*endcapLayers,0.); + std::vector<double> discRmin(2*endcapLayers,10e10); + std::vector<double> discRmax(2*endcapLayers,0); + std::vector<double> discThickness(2*endcapLayers,0.); + + std::vector< std::vector<Trk::SurfaceOrderPosition> > discSurfaces; + std::vector< std::vector<int> > discPhiSectors; + std::vector< std::vector<double> > discPhiMin; + std::vector< std::vector<double> > discPhiMax; + std::vector< std::vector<double> > discRingMinR; + std::vector< std::vector<double> > discRingMaxR; + + // let's make sure the discs are ordered in z: that's the z / map index + std::map< double, int> discZposLayerIndex; + + // reserve -- better memory management + discPhiMin.reserve(2*endcapLayers); + discPhiMax.reserve(2*endcapLayers); + discPhiSectors.reserve(2*endcapLayers); + discSurfaces.reserve(2*endcapLayers); + discRingMinR.reserve(2*endcapLayers); + discRingMaxR.reserve(2*endcapLayers); + + // initialize for checks (pos/neg discs -> 2 times discs) + for (unsigned int endcap=0; endcap<2*endcapLayers; endcap++){ + discPhiMin.push_back(std::vector<double>()); + discPhiMax.push_back(std::vector<double>()); + discPhiSectors.push_back(std::vector<int>()); + discSurfaces.push_back( std::vector<Trk::SurfaceOrderPosition>() ); + // auto-detection + discRingMinR.push_back(std::vector<double>()); + discRingMaxR.push_back(std::vector<double>()); + } // end of for loop + + int endcapModules = 0; + int sumCheckEndcapModules = 0; + unsigned int currentlayer = 0; + unsigned int currentdisk = 0; + unsigned int currentring = 0; + + // [-A1-] ------------------------ first LOOP over Detector Elements of sensitive layers ------------------------------- + // -- get the missing dimensions by loop over DetElements + sidetIter = readCdo->begin(); + for (; sidetIter != readCdo->end(); sidetIter++){ + // take it - if + // a) you have a detector element ... protection + // b) the detector element is EC (in the non-DBM case) + // c) the detector elemet is DBM in the DBM case + if ( (*sidetIter) && ( (!isDBM && (*sidetIter)->isEndcap()) || (isDBM && (*sidetIter)->isDBM())) ){ + + // increase the counter of endcap modules + endcapModules++; + // parse all z positions for the mean value of the discs + double currentZ = (*sidetIter)->center().z(); + // get the identifier & calculate current layer and current disk from it + Identifier currentId((*sidetIter)->identify()); + currentdisk = m_pixIdHelper ? m_pixIdHelper->layer_disk(currentId) : m_sctIdHelper->layer_disk(currentId); + currentlayer = currentdisk; + currentlayer += currentZ > 0. ? endcapLayers : 0; + + // check the current ring + currentring = m_pixIdHelper ? m_pixIdHelper->eta_module(currentId) : m_sctIdHelper->eta_module(currentId); + + takeSmallerBigger(discZmin[currentlayer],discZmax[currentlayer],currentZ); + + // set the disc Rmin / Rmax + double currentRmin = (*sidetIter)->rMin(); + double currentRmax = (*sidetIter)->rMax(); + + // how many rings do we have ? + unsigned int diskRings = isDBM ? + m_siMgr->numerology().numRingsForDiskDBM(currentdisk) : + m_siMgr->numerology().numRingsForDisk(currentdisk); + + // the current phi + double currentPhi = (*sidetIter)->center().phi(); + takeSmaller(discRmin[currentlayer],currentRmin); + takeBigger( discRmax[currentlayer],currentRmax); + + //fill the number of phi sectors for the different rings + if (!discPhiSectors[currentlayer].size()){ + ATH_MSG_VERBOSE("Pre-processing Elements from Disk/Layer (id from idHelper): " << currentdisk << "/" << currentlayer ); + // prepare the ring bins, initialise the first one to be something big + discPhiMin[currentlayer] = std::vector<double>(diskRings,100.); + discPhiMax[currentlayer] = std::vector<double>(diskRings,-100.); + discRingMinR[currentlayer] = std::vector<double>(diskRings,1e10); + discRingMaxR[currentlayer] = std::vector<double>(diskRings,0); + // fill the phi sectors + ATH_MSG_VERBOSE("-> The current disk has " << diskRings << " ring(s)"); + for (unsigned int iring=0; iring < diskRings; ++iring){ + unsigned int phiSectorsRing = isDBM ? + m_siMgr->numerology().numPhiModulesForDiskRingDBM(currentdisk, iring) : + m_siMgr->numerology().numPhiModulesForDiskRing(currentdisk, iring); + // get the number of phi sectors + ATH_MSG_VERBOSE("--> Ring " << iring << " has " << phiSectorsRing << " phi sectors"); + discPhiSectors[currentlayer].push_back(phiSectorsRing); + } + } + // we take the phi / r binning only from the closer to IP module + if ( !(*sidetIter)->otherSide() || fabs(currentZ) < fabs((*sidetIter)->otherSide()->center().z())){ + // take phi-min and phimax + takeSmaller(discPhiMin[currentlayer][currentring],currentPhi); + takeBigger(discPhiMax[currentlayer][currentring],currentPhi); + // record the smalles ring & biggest ring radius + takeSmaller(discRingMinR[currentlayer][currentring],currentRmin); + takeBigger(discRingMaxR[currentlayer][currentring],currentRmax); + } + } else if (!(*sidetIter)) + ATH_MSG_WARNING("NULL pointer to Endcap module given by SCT_DetectorManager! Please check db & dict.xml"); + } // DetElement loop + + double minRmin = 10e10; + double maxRmax = -10e10; + + ATH_MSG_VERBOSE("Estimating the average z position and the radius for each disk."); + // get the average z-position per layer & estimate thes thickness + for (unsigned int iec=0; iec<2*endcapLayers; ++iec){ + takeSmaller(minRmin,discRmin[iec]); takeBigger(maxRmax,discRmax[iec]); + // average it out + discZpos[iec] = 0.5 * (discZmin[iec] + discZmax[iec]); + discThickness[iec] = isDBM ? 1. : fabs(discZmax[iec]-discZmin[iec]); + // make the map z / index + discZposLayerIndex.insert(std::make_pair(discZpos[iec],iec)); + } + + // [-A2-] ------------------------ second LOOP over Detector Elements of sensitive layers ------------------------------- + // fill the elements for the layers into the surface arrays + sidetIter = readCdo->begin(); + for (; sidetIter != readCdo->end(); sidetIter++){ + // Endcap + if ( ((*sidetIter) && ((!isDBM && (*sidetIter)->isEndcap()) || (isDBM && (*sidetIter)->isDBM()))) ){ + // get the identifier & calculate current layer and current disk from it + Identifier currentId((*sidetIter)->identify()); + currentdisk = m_pixIdHelper ? m_pixIdHelper->layer_disk(currentId) : m_sctIdHelper->layer_disk(currentId); + currentlayer = currentdisk; + currentlayer += (*sidetIter)->center().z() > 0. ? endcapLayers : 0; + // decision which module to take + const InDetDD::SiDetectorElement* otherSide = (*sidetIter)->otherSide(); + bool takeIt = (!otherSide || fabs((*sidetIter)->center().z()) < fabs(otherSide->center().z()) ); + const InDetDD::SiDetectorElement* chosenSide = takeIt ? (*sidetIter) : otherSide; + // get the center position + const Amg::Vector3D& orderPosition = chosenSide->center(); + // register the chosen side in the object array + Trk::SharedObject<const Trk::Surface> sharedSurface(&(chosenSide->surface()), [](const Trk::Surface*){}); + Trk::SurfaceOrderPosition surfaceOrder(sharedSurface, orderPosition); + if (takeIt) (discSurfaces[currentlayer]).push_back(surfaceOrder); + } + } //end of filling + + // [-B-] ------------------------ Construction of the layers ----------------------------------- + // construct the layers + std::vector< const Trk::DiscLayer* >* discLayers = dLayers ? dLayers : new std::vector< const Trk::DiscLayer* >; + std::vector<double>::iterator discZposIter = discZpos.begin(); + int discCounter = 0; + + for ( ; discZposIter != discZpos.end(); ++discZposIter){ + // the gathered R sectors + size_t discRsectors = (discPhiSectors[discCounter]).size(); + // dynamic estimation 1: estimate the layer thickness dynamically + double thickness = discThickness[discCounter]+m_endcapEnvelope; + // put rMin in and sort the bins + std::vector<double> discRingMinRcopy = discRingMinR[discCounter]; + std::sort(discRingMinRcopy.begin(), discRingMinRcopy.end()); + bool reverseRsectors = !(discRingMinRcopy == discRingMinR[discCounter]); + + // this causes a reverse order for the phi sectors + if (reverseRsectors){ + ATH_MSG_VERBOSE("Auto-detect: rings in R are in " << ( reverseRsectors ? "reversed" : "standard") << " order."); + std::reverse(discPhiSectors[discCounter].begin(),discPhiSectors[discCounter].end()); + std::reverse(discPhiMin[discCounter].begin(),discPhiMin[discCounter].end()); + std::reverse(discPhiMax[discCounter].begin(),discPhiMax[discCounter].end()); + std::reverse(discRingMaxR[discCounter].begin(),discRingMaxR[discCounter].end()); + } + // preperare the rboundaries + std::vector<float> discRboundaries; + discRboundaries.push_back(float(*discRingMinRcopy.begin())); + for ( std::vector<double>::iterator ringMaxRIter = discRingMaxR[discCounter].begin(); + ringMaxRIter != discRingMaxR[discCounter].end(); ++ringMaxRIter) + discRboundaries.push_back(float(*ringMaxRIter)); + + // screen output + ATH_MSG_DEBUG( "Building a DiscLayer with " << discRsectors << " R sectors. " ); + ATH_MSG_DEBUG( " -> At Z - Position : " << discZpos[discCounter] ); + ATH_MSG_DEBUG( " -> With Thickness : " << thickness << " i- ncludes envelope tolerance : " << m_endcapEnvelope ); + ATH_MSG_DEBUG( " -> With Rmin/Rmax (est) : " << discRmin[discCounter] << " / " << discRmax[discCounter] ); + ATH_MSG_DEBUG( " -> With Rings : " << discRsectors ); + + for (size_t irings=0; irings<discRsectors; ++irings) + ATH_MSG_DEBUG( " --> " << irings << " R sector has " << discPhiSectors[discCounter][irings] << " phi sectors. " ); + + // prepare the binned array, it can be with one to several rings + Trk::BinnedArray<Trk::Surface>* currentBinnedArray = 0; + std::vector<Trk::BinUtility*>* singleBinUtils = new std::vector<Trk::BinUtility*>; + bool weOwnSingleBinUtils{true}; + if (discRsectors==1){ + double halfPhiStep = M_PI/discPhiSectors[discCounter][0]; + // protection in case phi value was fluctuating around 0 or M_PI in parsing + if (fabs(discPhiMin[discCounter][0]+discPhiMax[discCounter][0])< halfPhiStep && fabs(discPhiMin[discCounter][0]) < 0.5*halfPhiStep ){ + ATH_MSG_VERBOSE("Detected module fluctuation around +/- M_PI, correcting for it."); + ATH_MSG_VERBOSE(" min phi / max phi detected : " << discPhiMin[discCounter][0] << " / " <<discPhiMax[discCounter][0] ); + discPhiMin[discCounter][0] += 2*halfPhiStep; + } + // prepare min phi and max phi & eventually a sub stepvalue + ATH_MSG_VERBOSE(" min phi / max phi detected : " << discPhiMin[discCounter][0] << " / " << discPhiMax[discCounter][0] ); + double minPhiCorrected = discPhiMin[discCounter][0]-halfPhiStep; + double maxPhiCorrected = discPhiMax[discCounter][0]+halfPhiStep; + // catch if the minPhi falls below M_PI + if (minPhiCorrected < -M_PI){ + minPhiCorrected += 2*halfPhiStep; + maxPhiCorrected += 2*halfPhiStep; + } + ATH_MSG_VERBOSE(" min phi / max phi corrected : " << minPhiCorrected << " / " << maxPhiCorrected ); + + ATH_MSG_VERBOSE("Constructing a one-dimensional BinnedArray with phiMin / phiMax (bins) = " + << minPhiCorrected << " / " << maxPhiCorrected + << " (" << discPhiSectors[discCounter][0] << ")"); + // an easier bin utility can be used + Trk::BinUtility* currentBinUtility = new Trk::BinUtility(discPhiSectors[discCounter][0] , + minPhiCorrected, + maxPhiCorrected, + Trk::closed, + Trk::binPhi); + // a one-dimensional BinnedArray is sufficient + currentBinnedArray = new Trk::BinnedArray1D<Trk::Surface>(discSurfaces[discCounter],currentBinUtility); + } else { + ATH_MSG_VERBOSE("Constructing a two-dimensional BinnedArray."); + // get the binning in R first (can still be improved with non-aequidistant binning) + Trk::BinUtility* currentSteerBinUtility = 0; + if (m_endcapComplexRingBinning && discRsectors > 1 ){ + // respecting the actual element boundaires + ATH_MSG_VERBOSE("Non-equidistant binning detected."); + // now create the bin utility + currentSteerBinUtility = new Trk::BinUtility(discRboundaries, + Trk::open, + Trk::binR); + } else + currentSteerBinUtility = new Trk::BinUtility(discRsectors, + discRmin[discCounter], + discRmax[discCounter], + Trk::open, + Trk::binR); + ATH_MSG_VERBOSE("Steering bin utility constructed as : " << *currentSteerBinUtility); + // the single phi bin utilities + //std::vector<Trk::BinUtility*>* singleBinUtils = new std::vector<Trk::BinUtility*>; + singleBinUtils->reserve(discRsectors); + for (size_t irings=0; irings < discRsectors; ++irings){ + double halfPhiStep = M_PI/discPhiSectors[discCounter][irings]; + ATH_MSG_VERBOSE(" min phi / max phi detected : " << discPhiMin[discCounter][irings] << " / " << discPhiMax[discCounter][irings] ); + double minPhiCorrected = discPhiMin[discCounter][irings]-halfPhiStep; + double maxPhiCorrected = discPhiMax[discCounter][irings]+halfPhiStep; + // catch if the minPhi falls below M_PI + if (minPhiCorrected < -M_PI){ + minPhiCorrected += 2*halfPhiStep; + maxPhiCorrected += 2*halfPhiStep; + } + ATH_MSG_VERBOSE(" min phi / max phi corrected : " << minPhiCorrected << " / " << maxPhiCorrected ); + ATH_MSG_VERBOSE("Constructing for ring " << irings << " phi utility with phiMin / phiMax (bins) = " + << minPhiCorrected << " / " << maxPhiCorrected << " (" << discPhiSectors[discCounter][irings] << ")") ; + singleBinUtils->push_back(new Trk::BinUtility(discPhiSectors[discCounter][irings], + minPhiCorrected, + maxPhiCorrected, + Trk::closed, + Trk::binPhi)); + } + // a two-dimensional BinnedArray is needed ; takes possession of singleBinUtils and + // will delete it on destruction. + weOwnSingleBinUtils=false; + currentBinnedArray = new Trk::BinnedArray1D1D<Trk::Surface>(discSurfaces[discCounter], + currentSteerBinUtility, + singleBinUtils); + } + + + int discSurfacesNum = (discSurfaces[discCounter]).size(); + ATH_MSG_DEBUG( "Constructed BinnedArray for DiscLayer with "<< discSurfacesNum << " SubSurfaces." ); + + // always run the geometry validation to catch flaws + + // checking for : + // - empty surface bins + // - doubly filled bins + std::map< const Trk::Surface*,Amg::Vector3D > uniqueSurfaceMap; + std::map< const Trk::Surface*,Amg::Vector3D >::iterator usmIter = uniqueSurfaceMap.end(); + // check the registered surfaces in the binned array + const std::vector<const Trk::Surface*>& arraySurfaces = currentBinnedArray->arrayObjects(); + size_t dsumCheckSurfaces = 0; + double lastPhi = 0.; + for (auto& asurfIter : arraySurfaces){ + if ( asurfIter ) { + ++dsumCheckSurfaces; + usmIter = uniqueSurfaceMap.find(asurfIter); + lastPhi = asurfIter->center().phi(); + if ( usmIter != uniqueSurfaceMap.end() ) + ATH_MSG_WARNING("Non-unique surface found with eta/phi = " << asurfIter->center().eta() << " / " << asurfIter->center().phi()); + else uniqueSurfaceMap[asurfIter] = asurfIter->center(); + } else + ATH_MSG_WARNING("Zero-pointer in array detected in this ring, last valid phi value was = " << lastPhi); + } + sumCheckEndcapModules += dsumCheckSurfaces; + + // force same size for material collection - may be refined later + double rMin = (m_splitMode || m_endcapRingLayout) ? discRmin[discCounter] : minRmin; + double rMax = (m_splitMode || m_endcapRingLayout) ? discRmax[discCounter] : maxRmax; + + ATH_MSG_DEBUG( " -> With Rmin/Rmax (corr) : " << minRmin << " / " << maxRmax ); + + // get the layer material from the helper method + const Trk::LayerMaterialProperties* layerMaterial = endcapLayerMaterial(rMin,rMax); + + // position & bounds of the active Layer + Amg::Transform3D* activeLayerTransform = new Amg::Transform3D; + bool weOwnActiveLayerTransform=true; + (*activeLayerTransform) = Amg::Translation3D(0.,0.,discZpos[discCounter]); + + Trk::DiscBounds* activeLayerBounds = new Trk::DiscBounds(rMin,rMax); + // prepare the right overlap descriptor + Trk::OverlapDescriptor* olDescriptor = 0; + if (m_pixelCase) + olDescriptor = new InDet::PixelOverlapDescriptor; + //else olDescriptor = new InDet::SCT_OverlapDescriptor; + else { + std::vector<Trk::BinUtility*>* binUtils = new std::vector<Trk::BinUtility*>; + if (singleBinUtils) { + std::vector<Trk::BinUtility*>::iterator binIter = singleBinUtils->begin(); + for ( ; binIter != singleBinUtils->end(); ++binIter){ + binUtils->push_back((*binIter)->clone()); + } + } + //DiscOverlapDescriptor takes possession of binUtils, will delete it on destruction. + // but *does not* manage currentBinnedArray. + olDescriptor = new InDet::DiscOverlapDescriptor(currentBinnedArray, binUtils); + } + + // layer creation; deletes currentBinnedArray in baseclass 'Layer' upon destruction + // activeLayerTransform deleted in 'Surface' baseclass + Trk::DiscLayer* activeLayer = new Trk::DiscLayer(activeLayerTransform, + activeLayerBounds, + currentBinnedArray, + *layerMaterial, + thickness, + olDescriptor); + weOwnActiveLayerTransform=false; + // cleanup + delete layerMaterial; + // register the layer to the surfaces --- if necessary to the other sie as well + const std::vector<const Trk::Surface*>& layerSurfaces = currentBinnedArray->arrayObjects(); + registerSurfacesToLayer(layerSurfaces,*activeLayer); + if (m_splitMode){ + ATH_MSG_DEBUG( "[ Split mode ] Checking if this layer needs to be cached." ); + if (m_splitMode < 0 && rMin > s_splitRadius){ + ATH_MSG_VERBOSE( " Split mode is negative and rMin > splitRadius (" << rMin << " > " << s_splitRadius << ")."); + ATH_MSG_VERBOSE( " -> Caching this disk."); + readHandle->range(s_splitIOVRange); + s_splitDiscLayers.push_back(activeLayer); + } + else if (m_splitMode > 0 && rMax < s_splitRadius){ + ATH_MSG_VERBOSE( " Split mode is positive and rMax < splitRadius (" << rMax << " < " << s_splitRadius << ")."); + ATH_MSG_VERBOSE( " -> Caching this disk."); + readHandle->range(s_splitIOVRange); + s_splitDiscLayers.push_back(activeLayer); + } + } else + discLayers->push_back(activeLayer); + // increase the disc counter by one + ++discCounter; + if (weOwnSingleBinUtils){ + delete singleBinUtils; + singleBinUtils=nullptr; + } + if (weOwnActiveLayerTransform){ + delete activeLayerTransform; + activeLayerTransform=nullptr; + } + } + + // multiply the check modules for SCT case + sumCheckEndcapModules *= (m_pixelCase) ? 1 : 2; + ATH_MSG_DEBUG( endcapModules << " Endcap Modules parsed for Disc Layer dimensions." ); + ATH_MSG_DEBUG( sumCheckEndcapModules << " Endcap Modules filled in Disc Layer Arrays." ); + if ( endcapModules-sumCheckEndcapModules ) + ATH_MSG_WARNING( endcapModules-sumCheckEndcapModules << " Modules not registered properly in binned array." ); + + + // sort the vector + Trk::DiscLayerSorterZ zSorter; + std::vector<const Trk::DiscLayer*>::iterator sortIter = discLayers->begin(); + std::vector<const Trk::DiscLayer*>::iterator sortEnd = discLayers->end(); + std::sort(sortIter, sortEnd, zSorter); + + // if there are additional layers to be built - never build for the DBM loop + if (m_endcapAdditionalLayerPosZ.size() && !isDBM){ + // sort also the additional layer z positions + auto addLayerIter = m_endcapAdditionalLayerPosZ.begin(); + auto addLayerIterEnd = m_endcapAdditionalLayerPosZ.end(); + auto addLayerTypeIter = m_endcapAdditionalLayerType.begin(); + // reassign the iterators + sortIter = discLayers->begin(); + sortEnd = discLayers->end(); + // get the last rmin / rmax + double lastRmin = 0.; + double lastRmax = 0.; + // build the additional layers ------------------------------------------- + for ( ; sortIter != sortEnd || addLayerIter != addLayerIterEnd; ){ + // cache befor last parameters are overwritten + double layerRmin = lastRmin; + double layerRmax = lastRmax; + double layerZposition = 0.; + // check if the z-position is smaller than the + if ( sortIter != sortEnd){ + // get the current z position to guarantee a symmetrical setup + layerZposition = (*sortIter)->surfaceRepresentation().center().z(); + // get the bounds for the rMin / rMax setting + const Trk::DiscBounds* currentBounds = dynamic_cast<const Trk::DiscBounds*>(&((*sortIter)->surfaceRepresentation().bounds())); + lastRmin = currentBounds ? currentBounds->rMin() : 0.; + lastRmax = currentBounds ? currentBounds->rMax() : 0.; + ++sortIter; + } + if ( addLayerIter != addLayerIterEnd){ + // symmetric setup around 0. + double rMin = layerZposition > 0. ? layerRmin : lastRmin; + double rMax = layerZposition > 0. ? layerRmax : lastRmax; + // the passive layer + Trk::DiscLayer* passiveLayer = 0; + // passive layer creation + Amg::Transform3D* passiveDiscTransf = new Amg::Transform3D; + (*passiveDiscTransf) = Amg::Translation3D(0.,0.,*addLayerIter); + if (*addLayerTypeIter){ + ATH_MSG_DEBUG("Building an additional DiscLayer w/o sensitive modules at"); + // create the material and the passive layer + const Trk::LayerMaterialProperties* passiveLayerMaterial = endcapLayerMaterial(rMin,rMax); + passiveLayer = new Trk::DiscLayer(passiveDiscTransf, + new Trk::DiscBounds(rMin,rMax), + *passiveLayerMaterial, + 1.*Gaudi::Units::mm); + } else + passiveLayer = new Trk::DiscLayer(passiveDiscTransf, new Trk::DiscBounds(rMin,rMax), 0); + ATH_MSG_DEBUG( " -> At Z - Position : " << *addLayerIter ); + ATH_MSG_DEBUG( " -> With Rmin/Rmax (corr) : " << rMin << " / " << rMax ); + + // increase the iterator and push back the new layer + ++addLayerIter; + discLayers->push_back(passiveLayer); + } + } // the additional layers are build ------------------------------------ + + // another round of sorting needed after adding the passive layers + sortIter = discLayers->begin(); + sortEnd = discLayers->end(); + std::sort(sortIter, sortEnd, zSorter); + } + + EventIDRange range; + readHandle->range(range); + delete readHandle; + return std::make_pair(range, discLayers); +} + + + +std::vector< const Trk::CylinderLayer* >* InDet::SiLayerBuilderCond::dressCylinderLayers(const std::vector< const Trk::CylinderLayer* >& detectionLayers ) const { + + + std::vector< const Trk::CylinderLayer* >* cylinderLayers = new std::vector< const Trk::CylinderLayer* >; + // --------------------------- start of additional layer construction loop ------------------------------- + // for the additional layer + if (m_barrelAdditionalLayerR.size()){ + auto cylLayerIter = detectionLayers.begin(); + auto cylLayerIterEnd = detectionLayers.end(); + auto addLayerIter = m_barrelAdditionalLayerR.begin(); + auto addLayerIterEnd = m_barrelAdditionalLayerR.end(); + auto addLayerTypeIter = m_barrelAdditionalLayerType.begin(); + auto addLayerTypeIterEnd = m_barrelAdditionalLayerType.end(); + double cylLayerExtend = 0; + for ( ; addLayerIter != addLayerIterEnd && addLayerTypeIter != addLayerTypeIterEnd; ) { + // build the passive layer if it is smaller the current cylLayerIter - or if it is the last one + if ( m_splitMode && s_splitCylinderLayers.size() ){ + ATH_MSG_DEBUG("Called in split mode with split radius = " << s_splitRadius ); + ATH_MSG_DEBUG("[- X -] Skipping additional layer " ); + ATH_MSG_DEBUG( " -> With Radius : " << *addLayerIter ); + // increase the additional layer radii + ++addLayerIter; ++addLayerTypeIter; + continue; + } + if ( cylLayerIter == cylLayerIterEnd || (*addLayerIter) < (*cylLayerIter)->bounds().r() ){ + cylLayerExtend = (cylLayerIter == cylLayerIterEnd) ? cylLayerExtend : (*cylLayerIter)->bounds().halflengthZ() ; + if ( (*addLayerTypeIter) ) { + ATH_MSG_DEBUG("[- M -] Building an additional CylinderLayer w/o sensitive modules"); + // the material for the passive layer + const Trk::LayerMaterialProperties* passiveLayerMaterial = barrelLayerMaterial(*addLayerIter,cylLayerExtend); + // create the passive layer + cylinderLayers->push_back(new Trk::CylinderLayer(new Trk::CylinderBounds(*addLayerIter,cylLayerExtend), + *passiveLayerMaterial, + 1.*Gaudi::Units::mm, + 0,0)); + // cleanup of the layer material -------------------------------------------------------------- + delete passiveLayerMaterial; + } else { + ATH_MSG_DEBUG("[- N -] Building an additional NavigationLayer for volume dimension control"); + // create the passive layer + cylinderLayers->push_back(new Trk::CylinderLayer(new Trk::CylinderBounds(*addLayerIter,cylLayerExtend),0)); + } + ATH_MSG_DEBUG( " -> With Radius : " << *addLayerIter ); + // increase the additional layer radii + ++addLayerIter; ++addLayerTypeIter; + continue; + } + ATH_MSG_DEBUG("[- D -] Registering detection CylinderLayer"); + ATH_MSG_DEBUG( " -> With Radius : " << (*cylLayerIter)->bounds().r() ); + cylinderLayers->push_back(*cylLayerIter); + ++cylLayerIter; + } + } else + for (auto& cylLayerIter : detectionLayers ) { + ATH_MSG_DEBUG("[- D -] Registering detection CylinderLayer"); + ATH_MSG_DEBUG( " -> With Radius : " << cylLayerIter->bounds().r() ); + cylinderLayers->push_back(cylLayerIter); + } + return cylinderLayers; +} + +const Trk::LayerMaterialProperties* InDet::SiLayerBuilderCond::barrelLayerMaterial(double r, double hz) const +{ + Trk::LayerMaterialProperties* layerMaterial = 0; + // --------------- material estimation ---------------------------------------------------------------- + // -- material with 1D binning + Trk::BinUtility layerBinUtilityZ(m_barrelLayerBinsZ, -hz, hz, Trk::open, Trk::binZ); + if (m_barrelLayerBinsPhi==1){ + layerMaterial = new Trk::BinnedLayerMaterial(layerBinUtilityZ); + } else { // -- material with 2D binning + Trk::BinUtility layerBinUtilityRPhiZ(m_barrelLayerBinsPhi, + -r*M_PI, r*M_PI, + Trk::closed, + Trk::binRPhi); + layerBinUtilityRPhiZ += layerBinUtilityZ; + layerMaterial = new Trk::BinnedLayerMaterial(layerBinUtilityRPhiZ); + } + // --------------- material estimation ---------------------------------------------------------------- + return layerMaterial; +} + +const Trk::LayerMaterialProperties* InDet::SiLayerBuilderCond::endcapLayerMaterial(double rMin, double rMax) const +{ + Trk::LayerMaterialProperties* layerMaterial = 0; + // --------------- material estimation ---------------------------------------------------------------- + + Trk::BinUtility layerBinUtilityR(m_endcapLayerBinsR,rMin,rMax,Trk::open, Trk::binR); + // -- material with 1D binning + if (m_endcapLayerBinsPhi==1){ + layerMaterial = new Trk::BinnedLayerMaterial(layerBinUtilityR); + } else { // -- material with 2D binning + Trk::BinUtility layerBinUtilityPhi(m_endcapLayerBinsPhi,-M_PI,M_PI,Trk::closed,Trk::binPhi); + layerBinUtilityR += layerBinUtilityPhi; + layerMaterial = new Trk::BinnedLayerMaterial(layerBinUtilityR); + } + // --------------- material estimation ---------------------------------------------------------------- + return layerMaterial; +} + +void InDet::SiLayerBuilderCond::registerSurfacesToLayer(const std::vector<const Trk::Surface*>& layerSurfaces, const Trk::Layer& lay) const +{ + if (!m_setLayerAssociation) return; + + std::vector<const Trk::Surface*>::const_iterator laySurfIter = layerSurfaces.begin(); + std::vector<const Trk::Surface*>::const_iterator laySurfIterEnd = layerSurfaces.end(); + // register the surfaces to the layer + for (; laySurfIter != laySurfIterEnd; ++laySurfIter){ + if (*laySurfIter) { + // register the current surface -------------------------------------------------------- + Trk::ILayerBuilderCond::associateLayer(lay, **laySurfIter); + const InDetDD::SiDetectorElement* detElement + = dynamic_cast<const InDetDD::SiDetectorElement*>((*laySurfIter)->associatedDetectorElement()); + // register the backise if necessary --------------------------------------------------- + const InDetDD::SiDetectorElement* otherSideElement = detElement ? detElement->otherSide() : 0; + const Trk::Surface* otherSideSurface = otherSideElement ? &(otherSideElement->surface()) : 0; + if (otherSideSurface) Trk::ILayerBuilderCond::associateLayer(lay, *otherSideSurface); + } + } + + return; +} + + diff --git a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/StagedTrackingGeometryBuilderCond.cxx b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/StagedTrackingGeometryBuilderCond.cxx new file mode 100755 index 00000000000..9ef48138b05 --- /dev/null +++ b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/StagedTrackingGeometryBuilderCond.cxx @@ -0,0 +1,718 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +//////////////////////////////////////////////////////////////////// +// StagedTrackingGeometryBuilderCond.cxx, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +// InDet +#include "InDetTrackingGeometry/StagedTrackingGeometryBuilderCond.h" +// EnvelopeDefinitionService +#include "SubDetectorEnvelopes/IEnvelopeDefSvc.h" +// Trk interfaces +#include "TrkDetDescrInterfaces/ILayerProviderCond.h" +#include "TrkDetDescrInterfaces/ITrackingVolumeCreator.h" +#include "TrkDetDescrInterfaces/ILayerArrayCreator.h" +// Trk Geometry stuff +#include "TrkDetDescrUtils/BinnedArray.h" +#include "TrkVolumes/VolumeBounds.h" +#include "TrkVolumes/CylinderVolumeBounds.h" +#include "TrkGeometry/TrackingVolume.h" +#include "TrkGeometry/TrackingGeometry.h" +#include "TrkGeometry/MagneticFieldProperties.h" +#include "TrkGeometry/Material.h" +#include "TrkGeometry/Layer.h" +#include "TrkGeometry/CylinderLayer.h" +#include "TrkGeometry/DiscLayer.h" +#include "TrkSurfaces/DiscBounds.h" +//Gaudi +#include "GaudiKernel/SystemOfUnits.h" +#include "GaudiKernel/MsgStream.h" +#include <boost/lexical_cast.hpp> + +// constructor +InDet::StagedTrackingGeometryBuilderCond::StagedTrackingGeometryBuilderCond(const std::string& t, const std::string& n, const IInterface* p) : + AthAlgTool(t,n,p), + Trk::TrackingVolumeManipulator(), + m_trackingVolumeCreator("Trk::CylinderVolumeCreator/CylinderVolumeCreator"), + m_layerArrayCreator("Trk::LayerArrayCreator/LayerArrayCreator"), + m_enclosingEnvelopeSvc("AtlasEnvelopeDefSvc", n), + m_layerEnvelopeCover(2*Gaudi::Units::mm), + m_buildBoundaryLayers(true), + m_replaceJointBoundaries(true), + m_materialProperties(0), + m_magneticFieldProperties(0), + m_indexStaticLayers(true), + m_checkForRingLayout(false), + m_ringTolerance(10*Gaudi::Units::mm), + m_namespace("InDet::"), + m_exitVolume("InDet::Containers::InnerDetector") +{ + declareInterface<Trk::IGeometryBuilderCond>(this); + // layer builders and their configurations + declareProperty("LayerBuilders", m_layerProviders); + declareProperty("LayerBinningTypeCenter", m_layerBinningTypeCenter); + declareProperty("LayerBinningTypeEndcap", m_layerBinningTypeEndcap); + declareProperty("ColorCodes", m_colorCodesConfig); + // envelope definition service + declareProperty("EnvelopeDefinitionSvc", m_enclosingEnvelopeSvc ); + declareProperty("VolumeEnclosureCylinderRadii", m_enclosingCylinderRadius); + declareProperty("VolumeEnclosureDiscPositions", m_enclosingDiscPositionZ); + // helper tools + declareProperty("TrackingVolumeCreator", m_trackingVolumeCreator); + declareProperty("LayerArrayCreator", m_layerArrayCreator); + // build the Boundary Layers + declareProperty("EnvelopeCover", m_layerEnvelopeCover); + declareProperty("BuildBoundaryLayers", m_buildBoundaryLayers); + declareProperty("ReplaceAllJointBoundaries", m_replaceJointBoundaries); + // force robust layer indexing + declareProperty("IndexStaticLayers", m_indexStaticLayers); + declareProperty("CheckForRingLayout", m_checkForRingLayout); + // volume namespace & contaienr name + declareProperty("VolumeNamespace", m_namespace); + declareProperty("ExitVolumeName", m_exitVolume); +} + +// destructor +InDet::StagedTrackingGeometryBuilderCond::~StagedTrackingGeometryBuilderCond() +{ + delete m_materialProperties; + delete m_magneticFieldProperties; +} + +// Athena standard methods +// initialize +StatusCode InDet::StagedTrackingGeometryBuilderCond::initialize() +{ + + // retrieve envelope definition service -------------------------------------------------- + if ( m_enclosingEnvelopeSvc.retrieve().isFailure() ){ + ATH_MSG_FATAL( "Could not retrieve EnvelopeDefinition service. Abort."); + return StatusCode::FAILURE; + } + + // Retrieve the layer builders ----------------------------------------------------------- + if (m_layerProviders.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool(s) " << m_layerProviders ); + return StatusCode::FAILURE; + } else + ATH_MSG_DEBUG( "Retrieved tool " << m_layerProviders ); + + // Retrieve the tracking volume creator ------------------------------------------------- + if (m_trackingVolumeCreator.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool " << m_trackingVolumeCreator ); + return StatusCode::FAILURE; + } else + ATH_MSG_DEBUG( "Retrieved tool " << m_trackingVolumeCreator ); + + // Retrieve the layer array creator ---------------------------------------------------- + if (m_layerArrayCreator.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool " << m_layerArrayCreator ); + return StatusCode::FAILURE; + } else + ATH_MSG_INFO( "Retrieved tool " << m_layerArrayCreator ); + + // Dummy MaterialProerties + m_materialProperties = new Trk::Material; + + ATH_MSG_INFO( "initialize() succesful" ); + + return StatusCode::SUCCESS; +} + +//FIXME: ctx, tVolPair not used yet, range not created +std::pair<EventIDRange, const Trk::TrackingGeometry*> InDet::StagedTrackingGeometryBuilderCond::trackingGeometry(const EventContext& ctx, std::pair<EventIDRange, const Trk::TrackingVolume*> /*tVolPair*/) const +{ + // only one assumption: + // layer builders are ordered in increasing r + ATH_MSG_DEBUG( "[ Start building the ID TrackingGeometry. ]"); + ATH_MSG_DEBUG( "[ STEP 0 ] : Getting overal dimensions from DetectorEnvelope service." ); + + //////////////////////////////////////////////////////////////////////////////////////////////////////// + // The Overall Geometry + Trk::TrackingGeometry* trackingGeometry = 0; + + // get the dimensions from the envelope service + RZPairVector& envelopeDefs = m_enclosingEnvelopeSvc->getInDetRZValues(); + ATH_MSG_VERBOSE(" -> retrieved Inner Detector envelope definitions at size " << envelopeDefs.size()); + double envelopeVolumeRadius = envelopeDefs[1].first; + double envelopeVolumeHalfZ = fabs(envelopeDefs[1].second); + ATH_MSG_VERBOSE(" -> envelope R/Z defined as : " << envelopeVolumeRadius << " / " << envelopeVolumeHalfZ ); + + ATH_MSG_DEBUG( "[ STEP 1 ] : Getting overal dimensions from the different layer builders." ); + size_t ilS = 0; + double maximumLayerExtendZ = 0.; + double maximumLayerRadius = 0.; + std::vector<InDet::LayerSetup> layerSetups; + EventIDRange range; + for ( auto& lProvider : m_layerProviders){ + // screen output + ATH_MSG_DEBUG( "[ LayerBuilder : '" << lProvider->identification() << "' ] being processed. " ); + // retrieve the layers + std::pair< EventIDRange, std::vector<const Trk::Layer*> > centralLayersPair = lProvider->centralLayers(ctx); + std::pair< EventIDRange, std::vector<const Trk::Layer*> > negativeLayersPair = lProvider->negativeLayers(ctx); + std::pair< EventIDRange, std::vector<const Trk::Layer*> > positiveLayersPair = lProvider->positiveLayers(ctx); + range=EventIDRange::intersect(range,centralLayersPair.first, negativeLayersPair.first, positiveLayersPair.first); + ATH_MSG_VERBOSE(" -> retrieved " << centralLayersPair.second.size() << " central layers."); + ATH_MSG_VERBOSE(" -> retrieved " << negativeLayersPair.second.size() << " layers on negative side."); + ATH_MSG_VERBOSE(" -> retrieved " << positiveLayersPair.second.size() << " layers on positive side."); + // getting the Layer setup from parsing the builder output + InDet::LayerSetup lSetup = estimateLayerSetup(lProvider->identification(), ilS, + negativeLayersPair.second,centralLayersPair.second,positiveLayersPair.second, + envelopeVolumeRadius, envelopeVolumeHalfZ); + // get the maxima - for R and Z + takeBigger(maximumLayerRadius, lSetup.rMax); + takeBigger(maximumLayerExtendZ, lSetup.zMax); + //layer setups for the second run + layerSetups.push_back(lSetup); + // increase counter + ++ilS; + } + ATH_MSG_VERBOSE(" -> layer max R/Z defined as : " << maximumLayerRadius << " / " << maximumLayerExtendZ ); + + // create a volume cache for: + // - ID volume, i.e. those that can be stacked into the overall container + std::vector<const Trk::TrackingVolume*> idVolumes; + + // create a layer setup cache for flushing when necessary + std::vector<InDet::LayerSetup> layerSetupCache; + + // we only need to take care of the last flush radius + double lastFlushRadius = 0.; + + // (I) PARSE THE LAYERS FOR OVERALL DIMENSIONS ------------------------------------------------------------- + ATH_MSG_DEBUG( "[ STEP 2 ] : Looping through the layer setups and flush them into the ID detector volume vector." ); + for ( auto& lSetup : layerSetups){ + // screen output + ATH_MSG_DEBUG( "[ Layer setup: '" << lSetup.identification << "' ] being processed, current cache size is " << layerSetupCache.size() ); + ATH_MSG_VERBOSE(" -> estimated dimensions for this layer setup are"); + ATH_MSG_VERBOSE(" -> central sector rMin / rMax / zMax : " + << lSetup.minRadiusCenter << " / " << lSetup.maxRadiusCenter << " / " << lSetup.zExtendCenter); + if (lSetup.buildEndcap) + ATH_MSG_VERBOSE(" -> endcap sector rMin / rMax / zMin / zMax : " + << lSetup.minRadiusEndcap << " / " << lSetup.maxRadiusEndcap << " / " << lSetup.minZextendEndcap << " / " << lSetup.maxZextendEndcap); + else + ATH_MSG_VERBOSE(" -> endcap is not being built."); + + // now check what is in the cache + // [a] nothing in the cache or new setup is compatible (in this case sectorZ are updated in all setups) + if (!layerSetupCache.size() || setupFitsCache(lSetup,layerSetupCache) ){ + ATH_MSG_VERBOSE(" -> cache is empty or new sector fits cache setup - add this one to the cache."); + } else { + // [b] cache is not empty - let's see what is going on: + ATH_MSG_VERBOSE(" -> new sector does not fit the current cache specs -> flushing the cache." ); + // create the outer boundary + double flushRadius = 0.5*(layerSetupCache[layerSetupCache.size()-1].rMax + lSetup.rMin); + // create a flush volume - clears the cache + const Trk::TrackingVolume* fVolume = createFlushVolume(layerSetupCache,lastFlushRadius,flushRadius,maximumLayerExtendZ); + // stuff it into the idVolume + idVolumes.push_back(fVolume); + // remember the last flush radius + lastFlushRadius = flushRadius; + } + // in any case, this setup needs to go into the cache + layerSetupCache.push_back(lSetup); + } + + // check if the cache is empty + if (layerSetupCache.size()){ + ATH_MSG_DEBUG( "[ STEP 3 ] : Flush the remaining cache into the ID detector volume vector." ); + // set the maximum radius to the last layer radius + double flushRadius = 0.5*(maximumLayerRadius + envelopeVolumeRadius); + const Trk::TrackingVolume* fVolume = createFlushVolume(layerSetupCache,lastFlushRadius,flushRadius,maximumLayerExtendZ); + // push it into the vector + idVolumes.push_back(fVolume); + lastFlushRadius = flushRadius; + } + + ATH_MSG_DEBUG( "[ STEP 4 ] : Create the ID detector volumes" ); + // build the central enclosure first + const Trk::TrackingVolume* centralEnclosure = m_trackingVolumeCreator->createGapTrackingVolume(*m_materialProperties, + lastFlushRadius, envelopeVolumeRadius, + -maximumLayerExtendZ, maximumLayerExtendZ, + 1, true, + m_namespace+"Gaps::CentralEnclosure"); + idVolumes.push_back(centralEnclosure); + // now lets create the container + std::string volumeName = m_namespace+"Detectors::Container"; + const Trk::TrackingVolume* idContainer = + m_trackingVolumeCreator->createContainerTrackingVolume(idVolumes, + *m_materialProperties, + volumeName, + m_buildBoundaryLayers, + m_replaceJointBoundaries); + // finally create the two endplates: negative + const Trk::TrackingVolume* negativeEnclosure = m_trackingVolumeCreator->createGapTrackingVolume(*m_materialProperties, + 0., envelopeVolumeRadius, + -envelopeVolumeHalfZ, -maximumLayerExtendZ, + 1, false, + m_namespace+"Gaps::NegativeEnclosure"); + + // finally create the two endplates: positive + const Trk::TrackingVolume* positiveEnclosure = m_trackingVolumeCreator->createGapTrackingVolume(*m_materialProperties, + 0., envelopeVolumeRadius, + maximumLayerExtendZ,envelopeVolumeHalfZ, + 1, false, + m_namespace+"Gaps::PositiveEnclosure"); + // and the final tracking volume + std::vector<const Trk::TrackingVolume*> enclosedVolumes; + enclosedVolumes.push_back(negativeEnclosure); + enclosedVolumes.push_back(idContainer); + enclosedVolumes.push_back(positiveEnclosure); + + const Trk::TrackingVolume* enclosedDetector = + m_trackingVolumeCreator->createContainerTrackingVolume(enclosedVolumes, + *m_materialProperties, + m_exitVolume, + m_buildBoundaryLayers, + m_replaceJointBoundaries); + + // create the TrackingGeometry ------------------------------------------------------ + trackingGeometry = new Trk::TrackingGeometry(enclosedDetector); + + if (m_indexStaticLayers) { + ATH_MSG_VERBOSE("Re-index the static layers ..."); + trackingGeometry->indexStaticLayers(Trk::Global); + } + + return std::make_pair(range, trackingGeometry); +} + +// finalize +StatusCode InDet::StagedTrackingGeometryBuilderCond::finalize() +{ + ATH_MSG_INFO( "finalize() successful" ); + return StatusCode::SUCCESS; +} + + +const Trk::TrackingVolume* InDet::StagedTrackingGeometryBuilderCond::packVolumeTriple(const InDet::LayerSetup& layerSetup, + double rMin, double& rMax, + double zMax, double zPosCentral) const +{ + + + ATH_MSG_VERBOSE( '\t' << '\t'<< "Pack provided Layers from '" << layerSetup.identification << "' triple into a container volume. " ); + + // create the strings + std::string volumeBase = m_namespace+"Detectors::"+layerSetup.identification; + + const Trk::TrackingVolume* negativeVolume = createTrackingVolume(layerSetup.negativeLayers, + rMin,rMax, + -zMax,-zPosCentral, + volumeBase+"::NegativeEndcap", + (Trk::BinningType)layerSetup.binningEndcap, + false); + + const Trk::TrackingVolume* centralVolume = + m_trackingVolumeCreator->createTrackingVolume(layerSetup.centralLayers, + *m_materialProperties, + rMin,rMax, + -zPosCentral,zPosCentral, + volumeBase+"::Barrel", + (Trk::BinningType)layerSetup.binningCenter); + + const Trk::TrackingVolume* positiveVolume = createTrackingVolume(layerSetup.positiveLayers, + rMin,rMax, + zPosCentral,zMax, + volumeBase+"::PositiveEndcap", + (Trk::BinningType)layerSetup.binningEndcap, + false); + + // the base volumes have been created + ATH_MSG_VERBOSE('\t' << '\t'<< "Volumes have been created, now pack them into a triple."); + // registerColorCode + negativeVolume->registerColorCode(layerSetup.colorCode); + centralVolume->registerColorCode(layerSetup.colorCode); + positiveVolume->registerColorCode(layerSetup.colorCode); + + // pack them together + std::vector<const Trk::TrackingVolume*> tripleVolumes; + tripleVolumes.push_back(negativeVolume); + tripleVolumes.push_back(centralVolume); + tripleVolumes.push_back(positiveVolume); + + // create the tiple container + const Trk::TrackingVolume* tripleContainer = + m_trackingVolumeCreator->createContainerTrackingVolume(tripleVolumes, + *m_materialProperties, + volumeBase, + m_buildBoundaryLayers, + m_replaceJointBoundaries); + + ATH_MSG_VERBOSE( '\t' << '\t'<< "Created container volume with bounds: " << tripleContainer->volumeBounds() ); + + return tripleContainer; +} + + +/** Private helper method, estimates the overal dimensions */ +InDet::LayerSetup InDet::StagedTrackingGeometryBuilderCond::estimateLayerSetup(const std::string& idName, size_t ilS, + const std::vector<const Trk::Layer*>& negLayers, + const std::vector<const Trk::Layer*>& cenLayers, + const std::vector<const Trk::Layer*>& posLayers, + double maxR, double maxZ) const +{ + // prepare the dimensions + double cenMinR = 10e10; + double cenMaxR = 0.; + double cenMinZ = 10e10; + double cenMaxZ = 0.; + double posMinR = 10e10; + double posMaxR = 0.; + double posMinZ = 10e10; + double posMaxZ = 0.; + // parse through the central layers first + estimateLayerDimensions(cenLayers, cenMinR, cenMaxR, cenMinZ, cenMaxZ); + // parse throught the positive layers - we assume a symmetric setup + estimateLayerDimensions(posLayers, posMinR, posMaxR, posMinZ, posMaxZ); + // reset to maxZ and and maxR if overs + if (posMaxZ > maxZ) { + ATH_MSG_WARNING("Estimated z extended of central sector bigger than maximal z extened. Resetting - may lose layers though."); + cenMaxZ = maxZ; + } else if (posMaxZ > maxZ) { + ATH_MSG_WARNING("Estimated z extended of endcap sector bigger than maximal z extened. Resetting - may lose layers though."); + posMaxZ = maxZ; + } + // reset the radial wones. + if (cenMaxR > maxR) { + ATH_MSG_WARNING("Estimated r extended of central sector bigger than maximal r extened. Resetting - may lose layers though."); + cenMaxR = maxR; + } + if (posMaxR > maxR) { + ATH_MSG_WARNING("Estimated r extended of endcap sector bigger than maximal r extened. Resetting - may lose layers though."); + posMaxR = maxR; + } + // create the layer setup class + return InDet::LayerSetup(idName, m_colorCodesConfig[ilS], + negLayers, cenLayers, posLayers, + cenMinR, cenMaxR, cenMaxZ, m_layerBinningTypeCenter[ilS], + posLayers.size(), posMinR, posMaxR, posMinZ, posMaxZ, m_layerBinningTypeEndcap[ilS]); +} + + +/** Private helper method to estimate the layer dimensions */ +void InDet::StagedTrackingGeometryBuilderCond::estimateLayerDimensions(const std::vector<const Trk::Layer*>& layers, + double& rMin, double& rMax, double& zMin, double& zMax) const +{ + // parse through the layers and estimate + for (auto& layer : layers){ + // the thickness of the layer needs to be taken into account + double thickness = layer->thickness(); + // get the center + const Amg::Vector3D& center = layer->surfaceRepresentation().center(); + // check if it is a cylinder layer + const Trk::CylinderLayer* cLayer = dynamic_cast<const Trk::CylinderLayer*>(layer); + if (cLayer){ + // now we have access to all the information + double rMinC = cLayer->surfaceRepresentation().bounds().r()-0.5*thickness-m_layerEnvelopeCover; + double rMaxC = cLayer->surfaceRepresentation().bounds().r()+0.5*thickness+m_layerEnvelopeCover; + double hZ = cLayer->surfaceRepresentation().bounds().halflengthZ(); + takeSmaller(rMin,rMinC); + takeBigger(rMax,rMaxC); + takeSmaller(zMin,center.z()-hZ); + takeBigger(zMax,center.z()+hZ); + } + // proceed further if it is a Disc layer + const Trk::DiscBounds* dBounds = dynamic_cast<const Trk::DiscBounds*>(&(layer->surfaceRepresentation().bounds())); + if (dBounds){ + // now we have access to all the information + double rMinD =dBounds->rMin(); + double rMaxD =dBounds->rMax(); + double zMinD = center.z()-0.5*thickness-m_layerEnvelopeCover; + double zMaxD = center.z()+0.5*thickness+m_layerEnvelopeCover; + takeSmaller(rMin,rMinD); + takeBigger(rMax,rMaxD); + takeSmaller(zMin,zMinD); + takeBigger(zMax,zMaxD); + } + } +} + + +/** Private helper method to check if a sector is compatible with the cache */ +bool InDet::StagedTrackingGeometryBuilderCond::setupFitsCache(LayerSetup& layerSetup, std::vector<InDet::LayerSetup>& layerSetupCache) const +{ + // the maximum center and overall extend of the cache + double maxCenterCacheZ = 0.; + // the maximum endcap extend of the cache + double minEndcapCacheZ = 10e10; + // chech if he have a fullSectorSetup + bool fullSectorSetup = false; + // + for (auto& lCacheSetup : layerSetupCache){ + takeBigger(maxCenterCacheZ, lCacheSetup.zExtendCenter); + takeSmaller(minEndcapCacheZ, lCacheSetup.minZextendEndcap); + // once true always true - otherwise it would have been flushed + fullSectorSetup = lCacheSetup.buildEndcap ? true : fullSectorSetup; + + } + // if we do not have a full sector setup - > flush directly + if (!fullSectorSetup) { + ATH_MSG_VERBOSE(" -> only central sector being built, flush the cache ... "); + return false; + } + // if the cached minimum z endcap z extend cuts within the new barrel -> flush it + if (minEndcapCacheZ < layerSetup.zExtendCenter){ + ATH_MSG_VERBOSE(" -> cache endcap extend reaches into new central sector, flush the cache ... "); + return false; + } + // the cache center maximumg exceeds the new endcap minimum -> does not fit + if (maxCenterCacheZ < layerSetup.minZextendEndcap ) { + ATH_MSG_VERBOSE(" -> sector fully fits into cache! Add it and start synchronising ..."); + // calculate the new sector gap and synchronise + double newCenterMaxZ = maxCenterCacheZ > layerSetup.zExtendCenter ? maxCenterCacheZ : layerSetup.zExtendCenter; + double newEndcapMinZ = minEndcapCacheZ < layerSetup.minZextendEndcap ? minEndcapCacheZ : layerSetup.minZextendEndcap; + double newSectorZ = 0.5*(newCenterMaxZ+newEndcapMinZ); + // and syncrhonise the boundaries + for (auto& lCacheSetup : layerSetupCache) + lCacheSetup.zSector = newSectorZ; + layerSetup.zSector = newSectorZ; + return true; + } + // it simply does not fit so return false + return false; +} + +bool InDet::StagedTrackingGeometryBuilderCond::ringLayout(const std::vector<const Trk::Layer*>& layers, std::vector<double>& rmins, std::vector<double>& rmaxs) const { + // get the maximum extent in z + ATH_MSG_INFO("Checking for Ring layout ... "); + for (auto& ring : layers){ + // Surface + const Trk::Surface& ringSurface = ring->surfaceRepresentation(); + const Trk::DiscBounds* ringBounds = dynamic_cast<const Trk::DiscBounds*>(&(ringSurface.bounds())); + if (ringBounds){ + // get the main parameters + double zpos = ringSurface.center().z(); + double rMin = ringBounds->rMin(); + double rMax = ringBounds->rMax(); + // take and check + checkForInsert(rmins,rMin); + checkForInsert(rmaxs,rMax); + ATH_MSG_INFO(" -> Ring at z-position " << zpos << " - with rMin/rMax = " << rMin << "/" << rMax ); + } + } + return (rmins.size() > 1 ); +} + + + +const Trk::TrackingVolume* InDet::StagedTrackingGeometryBuilderCond::createTrackingVolume(const std::vector<const Trk::Layer*>& layers, + double innerRadius, double& outerRadius, + double zMin, double zMax, + const std::string& volumeName, + Trk::BinningType binningType, + bool doAdjustOuterRadius) const +{ + + // first loop - this is for diagnostics for the radii + std::vector<double> ringRmins; + std::vector<double> ringRmaxa; + if (m_checkForRingLayout && ringLayout(layers,ringRmins, ringRmaxa)){ + ATH_MSG_INFO("Ring layout is present for volume '" << volumeName << "' dealing with it."); + // create the vector for the sub volumes + std::vector<const Trk::TrackingVolume* > ringVolumes; + + // now sort the necessary layers --- for the sub volumes + std::vector< std::vector< const Trk::Layer*> > groupedDiscs(ringRmins.size(), std::vector< const Trk::Layer*>() ); + // second loop over the rings + for (auto& ring : layers){ + // Surface + const Trk::Surface& ringSurface = ring->surfaceRepresentation(); + const Trk::DiscBounds* ringBounds = dynamic_cast<const Trk::DiscBounds*>(&(ringSurface.bounds())); + if (ringBounds){ + // get the main parameters + double rMax = ringBounds->rMax(); + size_t rPos = 0; + // fill into the right group + for (auto& rm : ringRmaxa){ + if (rMax < rm+m_ringTolerance) break; + ++rPos; + } + // fill it it + const Trk::DiscLayer* dring = dynamic_cast<const Trk::DiscLayer*>(ring); + if (dring) groupedDiscs[rPos].push_back(dring); + } + } + // we are now grouped in cylinder rings per volume + for (int idset = 0; idset < int(groupedDiscs.size()); idset++){ + // always keep the boundaries in mind for the radial extend + double crmin = idset ? ringRmaxa[idset-1]+m_layerEnvelopeCover : innerRadius; + double crmax = ringRmaxa[idset]+m_layerEnvelopeCover; + if(idset==int(groupedDiscs.size())-1 && !doAdjustOuterRadius) crmax = outerRadius; + // now create the sub volume + std::string ringVolumeName = volumeName+"Ring"+boost::lexical_cast<std::string>(idset); + const Trk::TrackingVolume* ringVolume = m_trackingVolumeCreator->createTrackingVolume(groupedDiscs[idset], + *m_materialProperties, + crmin,crmax, + zMin,zMax, + ringVolumeName, + binningType); + // push back into the + ringVolumes.push_back(ringVolume); + } + // set the outer radius + if(doAdjustOuterRadius) outerRadius = ringRmaxa[ringRmaxa.size()-1]+m_layerEnvelopeCover; + // + ATH_MSG_INFO(" -> adjusting the outer radius to the last ring at " << outerRadius ); + ATH_MSG_INFO(" -> created " << ringVolumes.size() << " ring volumes for Volume '" << volumeName << "'."); + // create the tiple container + return m_trackingVolumeCreator->createContainerTrackingVolume(ringVolumes, + *m_materialProperties, + volumeName, + m_buildBoundaryLayers, + m_replaceJointBoundaries); + + + } else + return m_trackingVolumeCreator->createTrackingVolume(layers, + *m_materialProperties, + innerRadius,outerRadius, + zMin,zMax, + volumeName, + binningType); +} + + +/** Private helper method to flush the cache into the id volumes - return volume is the one to be provided */ +const Trk::TrackingVolume* InDet::StagedTrackingGeometryBuilderCond::createFlushVolume(std::vector<InDet::LayerSetup>& layerSetupCache, + double innerRadius, double& outerRadius, double extendZ) const +{ + // the return volume + const Trk::TrackingVolume* flushVolume = 0; + // + if (layerSetupCache.size() == 1 ){ + ATH_MSG_VERBOSE(" -> single sector setup - synchronising from inner (" << innerRadius << ") to outer (" << outerRadius << ") radius."); + ATH_MSG_VERBOSE(" -> setup identification : " << layerSetupCache[0].identification ); + // create the new tracking volume - either as a triple or as a single + flushVolume = layerSetupCache[0].buildEndcap ? + packVolumeTriple(layerSetupCache[0], + innerRadius, outerRadius, + extendZ,layerSetupCache[0].zSector) : + m_trackingVolumeCreator->createTrackingVolume(layerSetupCache[0].centralLayers, + *m_materialProperties, + innerRadius,outerRadius, + -extendZ,extendZ, + layerSetupCache[0].identification, + (Trk::BinningType)layerSetupCache[0].binningCenter); + + } else { + ATH_MSG_VERBOSE(" -> setup with " << layerSetupCache.size() << " entries - synchronising from inner (" << innerRadius << ") to outer (" << outerRadius << ") radius."); + // prepare the volume vectors & name identification + std::vector<const Trk::TrackingVolume*> negVolumes; + std::vector<const Trk::TrackingVolume*> centralVolumes; + std::vector<const Trk::TrackingVolume*> posVolumes; + std::string combinedName; + for (size_t ilS = 0; ilS < layerSetupCache.size(); ++ilS){ + // take the given inner radius for the first one - median otherwise + double irE = ilS ? 0.5*(layerSetupCache[ilS].minRadiusEndcap+layerSetupCache[ilS-1].maxRadiusEndcap) : innerRadius; + double irC = ilS ? 0.5*(layerSetupCache[ilS].minRadiusCenter+layerSetupCache[ilS-1].maxRadiusCenter) : innerRadius; + // take the given outer radius for the last one - median otherwise + double orE = ((ilS+1)==layerSetupCache.size()) ? outerRadius : 0.5*(layerSetupCache[ilS+1].minRadiusEndcap+layerSetupCache[ilS].maxRadiusEndcap); + double orC = ((ilS+1)==layerSetupCache.size()) ? outerRadius : 0.5*(layerSetupCache[ilS+1].minRadiusCenter+layerSetupCache[ilS].maxRadiusCenter); + // Adjust last volumes in R to the same maximal radial extends! + if(ilS==layerSetupCache.size()-1) { + ATH_MSG_VERBOSE("Processing last volume"); + ATH_MSG_VERBOSE(" --> adjust volumes to same extends: orE=" << orE << " orC=" << orC); + if(orE>orC) orC=orE; else orE=orC; + } + // create the three volumes + const Trk::TrackingVolume* nVolume = createTrackingVolume(layerSetupCache[ilS].negativeLayers, + irE,orE, + -extendZ,-layerSetupCache[ilS].zSector, + layerSetupCache[ilS].identification+"::NegativeEndcap", + (Trk::BinningType)layerSetupCache[ilS].binningEndcap,false); + const Trk::TrackingVolume* cVolume = m_trackingVolumeCreator->createTrackingVolume(layerSetupCache[ilS].centralLayers, + *m_materialProperties, + irC,orC, + -layerSetupCache[ilS].zSector,layerSetupCache[ilS].zSector, + layerSetupCache[ilS].identification+"::Barrel", + (Trk::BinningType)layerSetupCache[ilS].binningCenter); + const Trk::TrackingVolume* pVolume = createTrackingVolume(layerSetupCache[ilS].positiveLayers, + irE,orE, + layerSetupCache[ilS].zSector,extendZ, + layerSetupCache[ilS].identification+"::PositiveEndcap", + (Trk::BinningType)layerSetupCache[ilS].binningEndcap,false); + // register the right color code + nVolume->registerColorCode(layerSetupCache[ilS].colorCode); + cVolume->registerColorCode(layerSetupCache[ilS].colorCode); + pVolume->registerColorCode(layerSetupCache[ilS].colorCode); + // push them into the volume containers + negVolumes.push_back(nVolume); + centralVolumes.push_back(cVolume); + posVolumes.push_back(pVolume); + // combined name + combinedName += "_"+layerSetupCache[ilS].identification; + } + ATH_MSG_VERBOSE(" -> setup identification : " << combinedName ); + flushVolume = packVolumeTriple(negVolumes,centralVolumes,posVolumes,combinedName); + } + // clear the cache + layerSetupCache.clear(); + // return the volume + return flushVolume; + +} + +const Trk::TrackingVolume* InDet::StagedTrackingGeometryBuilderCond::packVolumeTriple( + const std::vector<const Trk::TrackingVolume*>& negVolumes, + const std::vector<const Trk::TrackingVolume*>& centralVolumes, + const std::vector<const Trk::TrackingVolume*>& posVolumes, + const std::string& baseName) const +{ + ATH_MSG_VERBOSE( '\t' << '\t'<< "Pack provided Volumes from '" << baseName << "' triple into a container volume. " ); + + unsigned int negVolSize = negVolumes.size(); + unsigned int cenVolSize = centralVolumes.size(); + unsigned int posVolSize = posVolumes.size(); + + + + // create the strings + std::string volumeBase = m_namespace+"Containers::"+baseName; + + const Trk::TrackingVolume* negativeVolume = (negVolSize > 1) ? + m_trackingVolumeCreator->createContainerTrackingVolume(negVolumes, + *m_materialProperties, + volumeBase+"::NegativeSector", + m_buildBoundaryLayers, + m_replaceJointBoundaries) : + (negVolSize ? negVolumes[0] : 0); + const Trk::TrackingVolume* centralVolume = (cenVolSize > 1) ? + m_trackingVolumeCreator->createContainerTrackingVolume(centralVolumes, + *m_materialProperties, + volumeBase+"::CentralSector", + m_buildBoundaryLayers, + m_replaceJointBoundaries) : + (cenVolSize ? centralVolumes[0] : 0) ; + + const Trk::TrackingVolume* positiveVolume = ( posVolSize > 1) ? + m_trackingVolumeCreator->createContainerTrackingVolume(posVolumes, + *m_materialProperties, + volumeBase+"::PositiveSector", + m_buildBoundaryLayers, + m_replaceJointBoundaries) : + (posVolSize ? posVolumes[0] : 0); + + if (!negativeVolume && !positiveVolume){ + ATH_MSG_DEBUG( "No negative/positive sector given - no packing needed, returning central container!" ); + return centralVolume; + } + // pack them together + std::vector<const Trk::TrackingVolume*> tripleVolumes; + if (negativeVolume) tripleVolumes.push_back(negativeVolume); + if (centralVolume) tripleVolumes.push_back(centralVolume); + if (positiveVolume) tripleVolumes.push_back(positiveVolume); + // create the tiple container + const Trk::TrackingVolume* tripleContainer = + m_trackingVolumeCreator->createContainerTrackingVolume(tripleVolumes, + *m_materialProperties, + volumeBase, + m_buildBoundaryLayers, + m_replaceJointBoundaries); + return tripleContainer; +} diff --git a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/TRT_LayerBuilderCond.cxx b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/TRT_LayerBuilderCond.cxx new file mode 100755 index 00000000000..90ac1dc3137 --- /dev/null +++ b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/TRT_LayerBuilderCond.cxx @@ -0,0 +1,729 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// TRT_LayerBuilderCond.cxx, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#include "InDetTrackingGeometry/TRT_LayerBuilderCond.h" +#include "InDetTrackingGeometry/TRT_OverlapDescriptor.h" +//Trk +#include "TrkSurfaces/Surface.h" +#include "TrkSurfaces/RectangleBounds.h" +#include "TrkSurfaces/DiscBounds.h" +#include "TrkGeometry/CylinderLayer.h" +#include "TrkGeometry/PlaneLayer.h" +#include "TrkGeometry/DiscLayer.h" +#include "TrkGeometry/BinnedLayerMaterial.h" +#include "TrkGeometry/ApproachDescriptor.h" +#include "TrkDetDescrUtils/GeometryStatics.h" +#include "TrkDetDescrUtils/BinnedArrayArray.h" +#include "TrkDetDescrUtils/BinnedArray2D.h" +#include "TrkDetDescrUtils/BinnedArray1D.h" +#include "TrkDetDescrUtils/BinUtility.h" +#include "TrkDetDescrUtils/BinUtility.h" +// GeoPrimitives +#include "GeoPrimitives/GeoPrimitivesHelpers.h" +#include "GeoPrimitives/GeoPrimitivesToStringConverter.h" +// InDetDD +#include "TRT_ReadoutGeometry/TRT_DetectorManager.h" +#include "TRT_ReadoutGeometry/TRT_Numerology.h" +#include "InDetIdentifier/TRT_ID.h" +// Gaudi +#include "GaudiKernel/ISvcLocator.h" +#include "GaudiKernel/SmartDataPtr.h" +#include "GaudiKernel/SystemOfUnits.h" +// STL +#include <map> + +namespace { + template <class T> + class PtrVectorWrapper + { + public: + PtrVectorWrapper () + : m_ptr(new std::vector<const T *>) + { + } + + ~PtrVectorWrapper() { + if (m_ptr) { + for (const T *elm : *m_ptr ) { + delete elm; + } + m_ptr->clear(); + } + } + std::vector<const T *> &operator*() { return *m_ptr; } + const std::vector<const T *> &operator*() const { return *m_ptr; } + + std::vector<const T *> *operator->() { return m_ptr.get(); } + const std::vector<const T *> *operator->() const { return m_ptr.get(); } + + std::vector<const T *> *release() { return m_ptr.release(); } + + private: + std::unique_ptr<std::vector<const T *> > m_ptr; + }; + +} + +// constructor +InDet::TRT_LayerBuilderCond::TRT_LayerBuilderCond(const std::string& t, const std::string& n, const IInterface* p) : + AthAlgTool(t,n,p), + m_trtMgr(0), + m_trtMgrLocation("TRT"), + m_layerStrawRadius(2.0*Gaudi::Units::mm), + m_layerThickness(0.1*Gaudi::Units::mm), + m_modelGeometry(true), + m_modelBarrelLayers(7), + m_modelEndcapLayers(14), + m_barrelLayerBinsZ(25), + m_barrelLayerBinsPhi(1), + m_endcapLayerBinsR(25), + m_endcapLayerBinsPhi(1), + m_endcapConly(false), + m_registerStraws(false), + m_barrelSectorAtPiBoundary(16), + m_identification("TRT") +{ + declareInterface<Trk::ILayerBuilderCond>(this); + // properties from outside + declareProperty("TRT_DetManagerLocation", m_trtMgrLocation); + declareProperty("LayerThickness", m_layerThickness); + // material binning + declareProperty("BarrelLayerBinsZ" , m_barrelLayerBinsZ); + declareProperty("BarrelLayerBinsPhi" , m_barrelLayerBinsPhi); + declareProperty("EndcapLayerBinsR" , m_endcapLayerBinsR); + declareProperty("EndcapLayerBinsPhi" , m_endcapLayerBinsPhi); + // steering + declareProperty("ModelLayersOnly", m_modelGeometry); + declareProperty("ModelBarrelLayers", m_modelBarrelLayers); + declareProperty("ModelEndcapLayers", m_modelEndcapLayers); + declareProperty("EndcapConly", m_endcapConly); + declareProperty("RegisterStraws", m_registerStraws); + declareProperty("BarrelSectorAtPi", m_barrelSectorAtPiBoundary); + // identification + declareProperty("Identification" , m_identification); +} + +// destructor +InDet::TRT_LayerBuilderCond::~TRT_LayerBuilderCond() +{} + +// Athena standard methods +// initialize +StatusCode InDet::TRT_LayerBuilderCond::initialize() +{ + ATH_MSG_INFO( "initialize()" ); + // get TRT Detector Description Manager + if ((detStore()->retrieve(m_trtMgr, m_trtMgrLocation)).isFailure()) + ATH_MSG_ERROR( "Could not get TRT_DetectorManager, no layers for TRT Detector will be built. " ); + + return StatusCode::SUCCESS; +} + +// finalize +StatusCode InDet::TRT_LayerBuilderCond::finalize() +{ + ATH_MSG_INFO( "finalize() successful" ); + + return StatusCode::SUCCESS; +} + + +/** LayerBuilderCond interface method - returning Barrel-like layers */ +//FIXME: context object is unused, elements are retrieved from m_trtMgr instead of CondSvc +std::pair<EventIDRange, const std::vector< const Trk::CylinderLayer* >* > InDet::TRT_LayerBuilderCond::cylindricalLayers(const EventContext&) const +{ + + //create dummy infinite range + EventIDRange range; + if (!m_trtMgr) return std::pair<EventIDRange,const std::vector<const Trk::CylinderLayer* >* >(range,nullptr); + + ATH_MSG_DEBUG( "Building cylindrical layers for the TRT " ); + + PtrVectorWrapper<Trk::CylinderLayer> barrelLayers; + + // get Numerology and Id HElper + const InDetDD::TRT_Numerology* trtNums = m_trtMgr->getNumerology(); + + // get the TRT ID Helper + const TRT_ID* trtIdHelper = 0; + if (detStore()->retrieve(trtIdHelper, "TRT_ID").isFailure()) { + ATH_MSG_ERROR("Could not get TRT ID helper"); + return std::pair<EventIDRange,const std::vector<const Trk::CylinderLayer* >* >(range,nullptr); + } + + int nBarrelRings = trtNums->getNBarrelRings(); + int nBarrelPhiSectors = trtNums->getNBarrelPhi(); + double layerPhiStep = 2*M_PI/nBarrelPhiSectors; + + int nTotalBarrelLayers = 0; + + // get the overall dimensions + double rMin = 10e10; + double rMax = 0.; + + double layerZmax = 0.; + double layerZmin = 10e10; + + // pre-loop for overall layer numbers & some ordering --------------------------------------- + for (int ring=0; ring < nBarrelRings; ring++) { + // the number of barrel layers + int nBarrelLayers = trtNums->getNBarrelLayers(ring); + nTotalBarrelLayers += nBarrelLayers; + // loop over layers + for (int layer=0; layer < nBarrelLayers; layer++){ + for (int phisec=0; phisec <nBarrelPhiSectors; ++phisec) + { + for (int iposneg=0; iposneg<2; ++iposneg){ + // get the element + const InDetDD::TRT_BarrelElement* trtbar = m_trtMgr->getBarrelElement(iposneg, ring, phisec, layer); + + // get overall dimensions only one time + const Trk::PlaneSurface* elementSurface = dynamic_cast<const Trk::PlaneSurface*>(&(trtbar->surface())); + if (!elementSurface) { + ATH_MSG_WARNING( "elementSurface: dynamic_cast to Trk::PlaneSurface failed - skipping ... ring/layer/phisec/iposneg = " << ring << "/" << layer << "/" << phisec << "/" << iposneg ); + continue; + } + const Trk::RectangleBounds* elementBounds = dynamic_cast<const Trk::RectangleBounds*>(&(trtbar->bounds())); + if (!elementBounds) { + ATH_MSG_WARNING( "elementBounds: dynamic_cast to Trk::RectangleBounds failed - skipping ... ring/layer/phisec/iposneg = " << ring << "/" << layer << "/" << phisec << "/" << iposneg ); + continue; + } + double elementZcenter = (elementSurface->center()).z(); + double elementZmin = fabs(elementZcenter - elementBounds->halflengthY()); + double elementZmax = fabs(elementZcenter + elementBounds->halflengthY()); + // take what you need + takeSmaller(layerZmin, elementZmin); takeBigger(layerZmax, elementZmax); + // get the radial dimensions + double currentR = trtbar->center().perp(); + takeSmallerBigger(rMin,rMax,currentR); + } + } + } + } + + if (nTotalBarrelLayers==0) { + ATH_MSG_WARNING( "nTotalBarrelLayers = 0 ... aborting and returning 0 !" ); + return std::pair<EventIDRange,const std::vector<const Trk::CylinderLayer* >* >(range,nullptr); + } + + // calculate delta(R) steps and delta(R) + double rDiff = fabs(rMax-rMin); + double rStep = rDiff/(m_modelBarrelLayers+1); + double layerHalflength = layerZmax; + + // prepare the material + if ( fabs(rDiff) <= 0.1 ){ + return std::pair<EventIDRange,const std::vector<const Trk::CylinderLayer* >* >(range,nullptr); + } + + // ilay - for accessing the straw layers and for material decission + int ilay = 0; + + // fix the positions where the layers are - these are used for the model geometry and the complex geometry --------------- + std::vector<double> layerRadii; + layerRadii.reserve(m_modelBarrelLayers); + for (unsigned int ilay = 1; ilay <= m_modelBarrelLayers; ++ilay) + layerRadii.push_back(rMin+ilay*rStep-0.5*m_layerThickness); + // these are the layer iterators + auto layerRadiusIter = layerRadii.begin(); + auto layerRadiusIterEnd = layerRadii.end(); + + // (A) model geometry section + if (m_modelGeometry && !m_registerStraws){ + + ATH_MSG_VERBOSE( " -> " << layerRadii.size() << " cylindrical barrel layers between " << rMin << " and " << rMax << " ( at step "<< rStep << " )"); + + // create the layers + for ( ; layerRadiusIter != layerRadiusIterEnd; ++layerRadiusIter ) { + // ----- prepare the BinnedLayerMaterial ----------------------------------------------------- + Trk::BinnedLayerMaterial* layerMaterial = 0; + // -- material with 1D binning + Trk::BinUtility layerBinUtility1DZ(m_barrelLayerBinsZ,-layerHalflength, layerHalflength, Trk::open, Trk::binZ); + if (m_barrelLayerBinsPhi==1){ + // no binning in phi + layerMaterial =new Trk::BinnedLayerMaterial(layerBinUtility1DZ); + } else { // -- material with 2D binning : Rphi*Z optimized for cylinder layer + Trk::BinUtility layerBinUtility2DRPhiZ(m_barrelLayerBinsPhi, + -(*layerRadiusIter)*M_PI, + (*layerRadiusIter)*M_PI, + Trk::closed, + Trk::binRPhi); + layerBinUtility2DRPhiZ += layerBinUtility1DZ; + layerMaterial =new Trk::BinnedLayerMaterial(layerBinUtility2DRPhiZ); + } + // Barrel layers are centered around (0,0,0) by definition + barrelLayers->push_back(new Trk::CylinderLayer(new Trk::CylinderBounds(*layerRadiusIter,layerHalflength), + *layerMaterial, + m_layerThickness)); + ATH_MSG_VERBOSE( " --> Creating a layer at radius : " << *layerRadiusIter ); + delete layerMaterial; + } + } else { + // (B) complex geometry section + + int nMaterialLayerStep = int(nTotalBarrelLayers/m_modelBarrelLayers+1); + int cMaterialLayerCount = 0; + + // loop over rings + ATH_MSG_VERBOSE("TRT Barrel has " << nBarrelRings << " rings."); + + for (int ring=0; ring < nBarrelRings; ring++){ + + int nBarrelLayers = trtNums->getNBarrelLayers(ring); + ATH_MSG_VERBOSE("-> Ring " << ring << " has " << nBarrelLayers << " barrel layers."); + // loop over layers + for (int layer=0; layer < nBarrelLayers; layer++){ + + // ---------------------------------------------------------------------------------- + ATH_MSG_VERBOSE("--> Layer " << layer << " is being built with " << nBarrelPhiSectors << " secors in phi."); + ++cMaterialLayerCount; + + // set layer dimensions radius + double layerRadius = 0.; + double layerRadiusMin = 10e10; + double layerRadiusMax = 0.; + double layerPhiMin = 10.; + double layerPhiMax = -10; + + // per phi sector we make a 2D binnin in phi-z + std::vector< std::pair<Trk::BinnedArray<Trk::Surface>*, Amg::Vector3D > > layerSectorArrays; + Amg::Vector3D layerSectorPosition(0.,0.,0.); + + // the sector approaching surfaces + std::vector< std::pair< Trk::SharedObject<const Trk::ApproachSurfaces>, Amg::Vector3D > > layerApproachSurfaces; + + // layer sector arrays + for (int phisec=0; phisec < nBarrelPhiSectors; phisec++){ + // ---------------------------------------------------------------------------------- + ATH_MSG_VERBOSE("---> Sector " << phisec << " gahtering the details."); + // -------------- a phi sector (expands in +/- z) ----------------------------------- + + // order the straws onto layers + std::vector< Trk::SurfaceOrderPosition > strawsPerPhiSecLayer; + // get the min an max phi, the min and max z + double phiMin = 10.; + double phiMax = -10.; + // sector stuff + int sectorStraws = 0; + // positive and negative sector + for (int posneg=0; posneg<2; ++posneg){ + // sort the elements + const InDetDD::TRT_BarrelElement* currentElement = m_trtMgr->getBarrelElement(posneg, ring, phisec, layer); + // get overall dimensions only one time + const Trk::PlaneSurface* elementSurface = dynamic_cast<const Trk::PlaneSurface*>(&(currentElement->surface())); + if (!elementSurface) { + ATH_MSG_WARNING( "elementSurface: dynamic_cast to Trk::PlaneSurface failed - skipping ... ring/layer/phisec/posneg = " << ring << "/" << layer << "/" << phisec << "/" << posneg ); + continue; + } + + // create teh approach surfaces -------------------------------------------------------------------------------------------------- + // getTransformFromRotTransl(Amg::RotationMatrix3D rot, Amg::Vector3D transl_vec ) + Trk::ApproachSurfaces* aSurfaces = new Trk::ApproachSurfaces; + const Amg::Transform3D& elementTransform = elementSurface->transform(); + const Amg::Vector3D& elementCenter = elementSurface->center(); + const Amg::Vector3D& elementNormal = elementSurface->normal(); + Amg::RotationMatrix3D elementRotation = elementTransform.rotation(); + // outer / inner + Amg::Vector3D outerCenter(elementCenter+(0.5*m_layerThickness+m_layerStrawRadius)*elementNormal); + Amg::Vector3D innerCenter(elementCenter-(0.5*m_layerThickness+m_layerStrawRadius)*elementNormal); + + // assign the layer sector position for the straw array ordering + layerSectorPosition = elementSurface->center(); + + // now register the two surfaces + aSurfaces->push_back(new Trk::PlaneSurface(new Amg::Transform3D(Amg::getTransformFromRotTransl(elementRotation, innerCenter)))); + aSurfaces->push_back(new Trk::PlaneSurface(new Amg::Transform3D(Amg::getTransformFromRotTransl(elementRotation, outerCenter)))); + + // now register it to for building the array + layerApproachSurfaces.push_back( std::pair< Trk::SharedObject<const Trk::ApproachSurfaces>, Amg::Vector3D >( Trk::SharedObject<const Trk::ApproachSurfaces>(aSurfaces),elementCenter)); + // screen output + ATH_MSG_VERBOSE("---> Sector " << phisec << " - posneg - " << posneg << " - with central phi = " << elementSurface->center().phi() ); + // sector phi centers + takeSmallerBigger(layerPhiMin,layerPhiMax,elementSurface->center().phi()); + + // loop over straws, fill them and find the phi boundaries + for (unsigned int istraw=0; istraw<currentElement->nStraws(); ++istraw) + { + Identifier strawId = trtIdHelper->straw_id(currentElement->identify(), istraw); + const Trk::Surface* currentStraw = &(currentElement->surface(strawId)); + // get the phi values + double currentPhi = currentStraw->center().phi(); + if (phisec == m_barrelSectorAtPiBoundary && currentPhi < 0.){ + currentPhi = M_PI + currentPhi; + currentPhi += M_PI; + } + // the layer radius + takeSmallerBigger(layerRadiusMin,layerRadiusMax,currentStraw->center().perp()); + takeSmallerBigger(phiMin, phiMax, currentPhi); + // make the ordering position + Amg::Vector3D strawOrderPos(currentStraw->center()); + //Trk::SharedObject<const Trk::Surface> sharedSurface(currentStraw, true); + /* + * The above line was using the nodel (not delete option for the old shared object + * now that SharedObject is a shared_ptr typeded do the same with empty deleter + */ + Trk::SharedObject<const Trk::Surface> sharedSurface(currentStraw, Trk::do_not_delete<const Trk::Surface>); + strawsPerPhiSecLayer.push_back(Trk::SurfaceOrderPosition(sharedSurface, strawOrderPos)); + // and record + ++sectorStraws; + } // loop over straws done + } // loop over posneg done + // show the phiMin/phiMax to the screen + // prepare the + // fix to CID 24918 + if (!sectorStraws) { + return std::pair<EventIDRange,const std::vector<const Trk::CylinderLayer* >* >(range,nullptr); + } + double deltaPhi = (phiMax-phiMin); + double phiStep = deltaPhi/(0.5*sectorStraws-1); + ATH_MSG_VERBOSE("---> Sector " << phisec << " - with " << 0.5*sectorStraws << " straws - straw phiMin/phiMax (step) = " << phiMin << " / " << phiMax << " (" << phiStep << ")"); + // phi min / phi max + phiMin -= 0.5*phiStep; + phiMax += 0.5*phiStep; + // correct for the +pi/-pi module + // now create the BinUtility + Trk::BinUtility* layerStrawPhiZUtility = new Trk::BinUtility(sectorStraws/2,phiMin,phiMax,Trk::open, Trk::binPhi); + (*layerStrawPhiZUtility) += Trk::BinUtility(2,-layerZmax, layerZmax, Trk::open, Trk::binZ); + // create the 2D BinnedArray + Trk::BinnedArray2D<Trk::Surface>* layerStrawPhiSector = new Trk::BinnedArray2D<Trk::Surface>(strawsPerPhiSecLayer,layerStrawPhiZUtility); + ATH_MSG_VERBOSE("---> Sector " << phisec << " - BinnedArray for straws prepared for " << strawsPerPhiSecLayer.size() << " straws."); + // fill the array + layerSectorArrays.push_back(std::pair< Trk::BinnedArray<Trk::Surface>*, Amg::Vector3D >(layerStrawPhiSector, layerSectorPosition)); + // ---------------- enf of phi sector ---------------------------------------------------- + } // loop over PhiSectors done + + // build the mean of the layer Radius + layerRadius = 0.5*(layerRadiusMin+layerRadiusMax)+0.5*m_layerStrawRadius; + + bool assignMaterial = false; + if (cMaterialLayerCount == nMaterialLayerStep) { + assignMaterial = true; + cMaterialLayerCount = 0; + ATH_MSG_VERBOSE( "--> Creating a material+straw layer at radius : " << layerRadius ); + } else + ATH_MSG_VERBOSE( "--> Creating a straw layer at radius : " << layerRadius ); + + // now order the plane layers to sit on cylindrical layers + Trk::CylinderBounds* barrelLayerBounds = new Trk::CylinderBounds(layerRadius, layerHalflength); + + // ---- correct phi ------------------------------------------------------------------- + ATH_MSG_VERBOSE(" prepare approach description with " << nBarrelPhiSectors << " barrel sectors."); + ATH_MSG_VERBOSE(" min phi / max phi detected : " << layerPhiMin << " / " << layerPhiMax ); + double layerPhiMinCorrected = layerPhiMin-0.5*layerPhiStep; + double layerPhiMaxCorrected = layerPhiMax+0.5*layerPhiStep; + // catch if the minPhi falls below M_PI + if (layerPhiMinCorrected < -M_PI){ + layerPhiMinCorrected += layerPhiStep; + layerPhiMaxCorrected += layerPhiStep; + } + ATH_MSG_VERBOSE(" min phi / max phi corrected : " << layerPhiMinCorrected << " / " << layerPhiMaxCorrected ); + + // the sector surfaces + Trk::BinUtility* layerSectorBinUtility = new Trk::BinUtility(nBarrelPhiSectors,layerPhiMinCorrected,layerPhiMaxCorrected,Trk::closed,Trk::binPhi); + Trk::BinnedArrayArray<Trk::Surface>* strawArray = new Trk::BinnedArrayArray<Trk::Surface>(layerSectorArrays, layerSectorBinUtility ); + + ATH_MSG_VERBOSE("--> Layer " << layer << " has been built with " << strawArray->arrayObjects().size() << " straws."); + + // ApproachDescriptor + // build a BinUtility for the ApproachDescritptor + Trk::BinUtility* aDescriptorBinUtility = new Trk::BinUtility(nBarrelPhiSectors,layerPhiMinCorrected,layerPhiMaxCorrected,Trk::closed,Trk::binPhi); + (*aDescriptorBinUtility) += Trk::BinUtility(2,-layerHalflength,layerHalflength,Trk::open, Trk::binZ); + Trk::BinnedArray2D<Trk::ApproachSurfaces>* aDescriptorBinnedArray = new Trk::BinnedArray2D<Trk::ApproachSurfaces> (layerApproachSurfaces, aDescriptorBinUtility); + // build an approach surface + Trk::CylinderSurface* approachSurface = new Trk::CylinderSurface(barrelLayerBounds->clone()); + Trk::ApproachDescriptor* aDescritpor = new Trk::ApproachDescriptor(aDescriptorBinnedArray, approachSurface); + + // do not give every layer material properties + if (assignMaterial) { + // ----- prepare the BinnedLayerMaterial ----------------------------------------------------- + Trk::BinnedLayerMaterial* layerMaterial = 0; + // -- material with 1D binning + Trk::BinUtility layerBinUtilityZ(m_barrelLayerBinsZ, -layerHalflength, layerHalflength, Trk::open, Trk::binZ ); + if (m_barrelLayerBinsPhi==1){ + layerMaterial =new Trk::BinnedLayerMaterial(layerBinUtilityZ); + } else { // -- material with 2D binning: RPhiZ binning + Trk::BinUtility layerBinUtilityRPhiZ(m_barrelLayerBinsPhi, + -layerRadius*M_PI, layerRadius*M_PI, + Trk::closed, + Trk::binRPhi); + layerBinUtilityRPhiZ += layerBinUtilityZ; + layerMaterial =new Trk::BinnedLayerMaterial(layerBinUtilityRPhiZ); + } + + barrelLayers->push_back(new Trk::CylinderLayer(barrelLayerBounds, + strawArray, + *layerMaterial, + m_layerThickness, + new InDet::TRT_OverlapDescriptor(trtIdHelper), + aDescritpor)); + delete layerMaterial; + + } else + barrelLayers->push_back(new Trk::CylinderLayer(barrelLayerBounds, + strawArray, + m_layerThickness, + new InDet::TRT_OverlapDescriptor(trtIdHelper), + aDescritpor)); + // increment this layer + ++ilay; + } // loop over layers + } // loop over rings + } + + // return what you have + return std::make_pair(range,barrelLayers.release()); +} + +//TODO: context object is unused, elements are retrieved from m_trtMgr instead of CondSvc +std::pair<EventIDRange, const std::vector< const Trk::DiscLayer* >* > InDet::TRT_LayerBuilderCond::discLayers(const EventContext&) const +{ + ATH_MSG_DEBUG( "Building disc-like layers for the TRT " ); + + //create dummy infinite range + EventIDRange range; + + const InDetDD::TRT_Numerology* trtNums = m_trtMgr->getNumerology(); + // get the TRT ID Helper + const TRT_ID* trtIdHelper = 0; + if (detStore()->retrieve(trtIdHelper, "TRT_ID").isFailure()) { + ATH_MSG_ERROR("Could not get TRT ID helper"); + return std::pair<EventIDRange,const std::vector<const Trk::DiscLayer* >* >(range,nullptr); + } + unsigned int nEndcapWheels = trtNums->getNEndcapWheels(); + unsigned int nEndcapPhiSectors = trtNums->getNEndcapPhi(); + + // total layer numbers + int numTotalLayers = 0; + + // zMin / zMax + double zMin = 10e10; + double zMax = 0.; + + const Trk::DiscBounds* sectorDiscBounds = 0; + + // preloop for overall numbers + for (unsigned int iwheel=0; iwheel<nEndcapWheels; ++iwheel) + { + unsigned int nEndcapLayers = trtNums->getNEndcapLayers(iwheel); + numTotalLayers += nEndcapLayers; + for (unsigned int ilayer = 0; ilayer<nEndcapLayers; ++ilayer){ + const InDetDD::TRT_EndcapElement* sectorDiscElement = m_trtMgr->getEndcapElement(0, iwheel, ilayer, 0); + + // get a reference element for dimensions + if (!sectorDiscBounds){ + const Trk::SurfaceBounds& sectorSurfaceBounds = sectorDiscElement->bounds(); + sectorDiscBounds = dynamic_cast<const Trk::DiscBounds*>(§orSurfaceBounds); + } + + double currentZ = fabs(sectorDiscElement->center().z()); + takeSmallerBigger(zMin,zMax,currentZ); + } + } + if (numTotalLayers==0) { + ATH_MSG_WARNING( "numTotalLayers = 0 ... aborting and returning 0 !" ); + return std::pair<EventIDRange,const std::vector<const Trk::DiscLayer* >* >(range,nullptr); + } + + Trk::DiscBounds* fullDiscBounds = sectorDiscBounds ? new Trk::DiscBounds(sectorDiscBounds->rMin(), sectorDiscBounds->rMax()) : 0; + if (!fullDiscBounds) { + ATH_MSG_WARNING( "fullDiscBounds do not exist ... aborting and returning 0 !" ); + return std::pair<EventIDRange,const std::vector<const Trk::DiscLayer* >* >(range,nullptr); + } + + PtrVectorWrapper<Trk::DiscLayer> endcapLayers; + + // the BinUtility for the material + Trk::BinnedLayerMaterial* layerMaterial = 0; + // -- material with 1D binning + Trk::BinUtility layerBinUtilityR(m_endcapLayerBinsR, + fullDiscBounds->rMin(), + fullDiscBounds->rMax(), + Trk::open, + Trk::binR); + if (m_barrelLayerBinsPhi==1) + layerMaterial = new Trk::BinnedLayerMaterial(layerBinUtilityR); + else { // -- material with 2D binning + Trk::BinUtility layerBinUtilityPhi(m_barrelLayerBinsPhi, + -M_PI, M_PI, + Trk::closed, + Trk::binPhi); + // make it rPhi now + layerBinUtilityR += layerBinUtilityPhi; + layerMaterial =new Trk::BinnedLayerMaterial(layerBinUtilityR); + } + + // global geometry statistics + double zDiff = fabs(zMax-zMin); + double zStep = zDiff/(m_modelEndcapLayers+1); + + // loop for surface ordering + int maxendcaps=2; + if (m_endcapConly) maxendcaps=1; + + for (int iposneg=0; iposneg<maxendcaps; ++iposneg){ + + // fill the positions of the disc layers + std::vector<double> zPositions; + zPositions.reserve(m_modelEndcapLayers); + + double stepdir = iposneg ? 1. : -1.; + double zStart = stepdir*zMin; + + ATH_MSG_VERBOSE( " -> Creating " << m_modelEndcapLayers << " disc-layers on each side between " + << zMin << " and " << zMax << " ( at step "<< zStep << " )"); + + // take a different modelling for the layers - use these layers for the model geometry and the real geometry + for (unsigned int izpos = 1; izpos <= m_modelEndcapLayers; ++izpos){ + zPositions.push_back(zStart + stepdir * double(izpos) * zStep - 0.5 * m_layerThickness); + } + + std::vector<double>::const_iterator zPosIter = zPositions.begin(); + std::vector<double>::const_iterator zPosIterEnd = zPositions.end(); + + // (a) simplified geometry + if (m_modelGeometry){ + // build the layers actually + for ( ; zPosIter != zPosIterEnd; ++zPosIter){ + ATH_MSG_VERBOSE( " --> Creating a layer at z pos : " << (*zPosIter) ); + Amg::Transform3D* zPosTrans = new Amg::Transform3D; + (*zPosTrans) = Amg::Translation3D(0.,0.,(*zPosIter)); + endcapLayers->push_back(new Trk::DiscLayer(zPosTrans, + fullDiscBounds->clone(), + *layerMaterial, + m_layerThickness)); + } + + } else { + // (b) complex geometry + int nMaterialLayerStep = int(numTotalLayers/m_modelEndcapLayers+1); + int cMaterialLayerCount = 0; + + // complex geometry - needs a little bit of joggling + int currentLayerCounter = 0; + for (unsigned int iwheel=0; iwheel<nEndcapWheels; ++iwheel) + { + // do the loop per side + unsigned int nEndcapLayers = trtNums->getNEndcapLayers(iwheel); + for (unsigned int ilayer = 0; ilayer < nEndcapLayers; ++ilayer){ + // increase the layerCounter for material layer decission + ++currentLayerCounter; + ++cMaterialLayerCount; + + // count the straws; + int numberOfStraws = 0; + + // check if dynamic cast worked + if (fullDiscBounds){ + // get a reference element for dimensions + const InDetDD::TRT_EndcapElement* sectorDiscElement = m_trtMgr->getEndcapElement(iposneg, iwheel, ilayer, 0); + + // take the position, but not the rotation (the rotation has to be standard) + Amg::Vector3D fullDiscPosition(sectorDiscElement->surface().transform().translation()); + double discZ = fullDiscPosition.z(); + + // check if we need to build a straw layer or not + bool assignMaterial = false; + if (cMaterialLayerCount == nMaterialLayerStep) { + assignMaterial = true; + cMaterialLayerCount = 0; + ATH_MSG_VERBOSE( "--> Creating a material+straw layer at z-pos : " << discZ ); + } else { + ATH_MSG_VERBOSE( "--> Creating a straw layer at z-pos : " << discZ ); + } + + // order the straws onto layers + std::vector< Trk::SurfaceOrderPosition > strawPerEndcapLayer; + + // the layer thickness - for approaching surfaces + double zMin = 10e10; + double zMax = -10e10; + + for (unsigned int iphisec=0; iphisec<nEndcapPhiSectors; ++iphisec){ + ATH_MSG_VERBOSE("Building sector " << iphisec << " of endcap wheel " << iwheel ); + const InDetDD::TRT_EndcapElement* currentElement = m_trtMgr->getEndcapElement(iposneg, iwheel, ilayer, iphisec); + unsigned int nstraws = currentElement->nStraws(); + for (unsigned int istraw=0; istraw<nstraws; istraw++){ + Identifier strawId = trtIdHelper->straw_id(currentElement->identify(), istraw); + const Trk::Surface* currentStraw = &(currentElement->surface(strawId)); + Amg::Vector3D strawOrderPos(currentStraw->center()); + // get the z position + double zPos = currentStraw->center().z(); + takeSmaller(zMin,zPos); + takeBigger(zMax,zPos); + Trk::SharedObject<const Trk::Surface> sharedSurface(currentStraw, [](const Trk::Surface*){}); + strawPerEndcapLayer.push_back(Trk::SurfaceOrderPosition(sharedSurface, strawOrderPos)); + ++numberOfStraws; + } + } + // fix to CID 11326 + if (!numberOfStraws){ + //fix coverity 118656 + delete fullDiscBounds; + return std::pair<EventIDRange,const std::vector<const Trk::DiscLayer* >* >(range,nullptr); + } + Trk::BinUtility* currentBinUtility = new Trk::BinUtility(numberOfStraws, -M_PI, M_PI, Trk::closed, Trk::binPhi); + Trk::BinnedArray<Trk::Surface>* strawArray = new Trk::BinnedArray1D<Trk::Surface>(strawPerEndcapLayer, currentBinUtility); + Trk::DiscLayer* currentLayer = 0; + + // redefine the discZ + discZ = 0.5*(zMin+zMax); + Amg::Transform3D* fullDiscTransform = new Amg::Transform3D; + (*fullDiscTransform) = Amg::Translation3D(0.,0.,discZ); + + ATH_MSG_VERBOSE("TRT Disc being build at z Position " << discZ << " ( from " << zMin << " / " << zMax << " )"); + + // create the approach offset + Trk::ApproachSurfaces* aSurfaces = new Trk::ApproachSurfaces; + // get the position of the approach surfaces + const Amg::Vector3D aspPosition(0.,0.,zMin-m_layerStrawRadius); + const Amg::Vector3D asnPosition(0.,0.,zMax+m_layerStrawRadius); + + // create new surfaces + Amg::Transform3D* asnTransform = new Amg::Transform3D(Amg::Translation3D(asnPosition)); + Amg::Transform3D* aspTransform = new Amg::Transform3D(Amg::Translation3D(aspPosition)); + // order in an optimised way for collision direction + if (discZ > 0.){ + aSurfaces->push_back( new Trk::DiscSurface(asnTransform, fullDiscBounds->clone()) ); + aSurfaces->push_back( new Trk::DiscSurface(aspTransform, fullDiscBounds->clone()) ); + } else { + aSurfaces->push_back( new Trk::DiscSurface(aspTransform, fullDiscBounds->clone()) ); + aSurfaces->push_back( new Trk::DiscSurface(asnTransform, fullDiscBounds->clone()) ); + } + // approach descriptor + Trk::ApproachDescriptor* aDescriptor = new Trk::ApproachDescriptor(aSurfaces,false); + + // do not give every layer material properties + if (assignMaterial) + currentLayer = new Trk::DiscLayer(fullDiscTransform, + fullDiscBounds->clone(), + strawArray, + *layerMaterial, + m_layerThickness, + new InDet::TRT_OverlapDescriptor(trtIdHelper), + aDescriptor); + else if (!m_modelGeometry) + currentLayer = new Trk::DiscLayer(fullDiscTransform, + fullDiscBounds->clone(), + strawArray, + m_layerThickness, + new InDet::TRT_OverlapDescriptor(trtIdHelper), + aDescriptor); + + if (currentLayer) endcapLayers->push_back(currentLayer); + } // end of sectorDiscBounds if + } // end of layer loop + } // end of wheel loop + } // model/real geometry + } // end of posneg loop + + delete layerMaterial; layerMaterial = 0; + delete fullDiscBounds; fullDiscBounds = 0; + + return std::make_pair(range,endcapLayers.release()); +} + diff --git a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/components/InDetTrackingGeometry_entries.cxx b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/components/InDetTrackingGeometry_entries.cxx index 53bdacb2e50..65ae2778d12 100644 --- a/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/components/InDetTrackingGeometry_entries.cxx +++ b/InnerDetector/InDetDetDescr/InDetTrackingGeometry/src/components/InDetTrackingGeometry_entries.cxx @@ -4,6 +4,12 @@ #include "InDetTrackingGeometry/RobustTrackingGeometryBuilder.h" #include "InDetTrackingGeometry/StagedTrackingGeometryBuilder.h" +#include "InDetTrackingGeometry/BeamPipeBuilderCond.h" +#include "InDetTrackingGeometry/SiLayerBuilderCond.h" +#include "InDetTrackingGeometry/TRT_LayerBuilderCond.h" +#include "InDetTrackingGeometry/RobustTrackingGeometryBuilderCond.h" +#include "InDetTrackingGeometry/StagedTrackingGeometryBuilderCond.h" + using namespace InDet; DECLARE_COMPONENT( BeamPipeBuilder ) @@ -12,3 +18,9 @@ DECLARE_COMPONENT( TRT_LayerBuilder ) DECLARE_COMPONENT( RobustTrackingGeometryBuilder ) DECLARE_COMPONENT( StagedTrackingGeometryBuilder ) +DECLARE_COMPONENT( BeamPipeBuilderCond ) +DECLARE_COMPONENT( SiLayerBuilderCond ) +DECLARE_COMPONENT( TRT_LayerBuilderCond ) +DECLARE_COMPONENT( RobustTrackingGeometryBuilderCond ) +DECLARE_COMPONENT( StagedTrackingGeometryBuilderCond ) + diff --git a/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/MuonTrackingGeometry/MuonTrackingGeometryBuilderCond.h b/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/MuonTrackingGeometry/MuonTrackingGeometryBuilderCond.h new file mode 100644 index 00000000000..40f179309c4 --- /dev/null +++ b/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/MuonTrackingGeometry/MuonTrackingGeometryBuilderCond.h @@ -0,0 +1,190 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// MuonTrackingGeometryBuilderCond.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef MUONTRACKINGGEOMETRY_MUONTRACKINGGEOMETRYBUILDERCOND_H +#define MUONTRACKINGGEOMETRY_MUONTRACKINGGEOMETRYBUILDERCOND_H + +//Trk +#include "TrkDetDescrInterfaces/IGeometryBuilderCond.h" +#include "TrkDetDescrUtils/GeometrySignature.h" +#include "TrkDetDescrInterfaces/ITrackingVolumeArrayCreator.h" +#include "TrkDetDescrInterfaces/ITrackingVolumeHelper.h" +// Gaudi +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/ToolHandle.h" +#include "GaudiKernel/ServiceHandle.h" +#include "GaudiKernel/IChronoStatSvc.h" +#include "MuonTrackingGeometry/MuonStationBuilder.h" +#include "MuonTrackingGeometry/MuonInertMaterialBuilder.h" +// EnvelopeDefinitionService +#include "SubDetectorEnvelopes/RZPair.h" +#include "SubDetectorEnvelopes/IEnvelopeDefSvc.h" + +namespace Trk { + class TrackingGeometry; + class Material; + class VolumeBounds; + class ITrackingVolumeBuilder; + + typedef std::pair< SharedObject<const TrackingVolume>, Amg::Vector3D> TrackingVolumeOrderPosition; + typedef std::pair< SharedObject<const TrackingVolume>, const Amg::Transform3D*> TrackingVolumeNavOrder; + +} + +namespace Muon { + + typedef std::vector<double> Span; + + /** @class MuonTrackingGeometryBuilderCond + + The Muon::MuonTrackingGeometryBuilderCond retrieves MuonStationBuilder and MuonInertMaterialBuilder + for the Muon Detector sub detectors and combines the given Volumes to a full Trk::TrackingGeometry. + + Inheriting directly from IGeometryBuilderCond it can use the protected member functions of the IGeometryBuilderCond + to glue Volumes together and exchange BoundarySurfaces + + @author Sarka.Todorova@cern.ch + */ + + class MuonTrackingGeometryBuilderCond : public AthAlgTool, + virtual public Trk::IGeometryBuilderCond { + public: + /** Constructor */ + MuonTrackingGeometryBuilderCond(const std::string&,const std::string&,const IInterface*); + /** Destructor */ + virtual ~MuonTrackingGeometryBuilderCond() = default; + /** AlgTool initailize method.*/ + StatusCode initialize(); + /** AlgTool finalize method */ + StatusCode finalize(); + /** TrackingGeometry Interface method */ + std::pair<EventIDRange, const Trk::TrackingGeometry*> trackingGeometry(const EventContext& ctx, std::pair<EventIDRange, const Trk::TrackingVolume*> tVolPair ) const; + + /** The unique signature */ + Trk::GeometrySignature geometrySignature() const { return Trk::MS; } + + private: + /** Private struct to contain local variables we dont want to be global in this class*/ + struct LocalVariablesContainer { + double m_innerBarrelRadius; + double m_outerBarrelRadius; + double m_innerEndcapZ; + double m_outerEndcapZ; + bool m_adjustStatic; + bool m_static3d; + std::vector<double> m_zPartitions; + std::vector<int> m_zPartitionsType; + std::vector<float> m_adjustedPhi; + std::vector<int> m_adjustedPhiType; + std::vector<const Span*> m_spans; // for clearing + std::vector<std::vector<std::vector<std::vector<std::pair<int,float> > > > > m_hPartitions; + std::vector<double> m_shieldZPart; + std::vector<std::vector<std::pair<int,float> > > m_shieldHPart; + std::map<const Trk::DetachedTrackingVolume*,std::vector<const Trk::TrackingVolume*>* > m_blendMap; + std::vector<const Trk::DetachedTrackingVolume*> m_blendVols; + const std::vector<std::vector<std::pair<const Trk::DetachedTrackingVolume*,const Span*> >* >* m_stationSpan; + const std::vector<std::vector<std::pair<const Trk::DetachedTrackingVolume*,const Span*> >* >* m_inertSpan; + RZPairVector m_msCutoutsIn; + RZPairVector m_msCutoutsOut; + Trk::Material m_muonMaterial; //!< the (empty) material + Trk::TrackingVolume* m_standaloneTrackingVolume; // muon standalone tracking volume + }; + + /** Private method to find z/phi span of detached volumes */ + const Span* findVolumeSpan(const Trk::VolumeBounds* volBounds, Amg::Transform3D transf, double zTol, double phiTol, LocalVariablesContainer &aLVC) const; + const std::vector<std::vector<std::pair<const Trk::DetachedTrackingVolume*,const Span*> >* >* findVolumesSpan(const std::vector<const Trk::DetachedTrackingVolume*>* objs, double zTol, double phiTol, LocalVariablesContainer &aLVC) const; + /** Private methods to define subvolumes and fill them with detached volumes */ + const Trk::TrackingVolume* processVolume( const Trk::Volume*, int, int, std::string, LocalVariablesContainer &aLVC) const; + const Trk::TrackingVolume* processVolume( const Trk::Volume*, int, std::string, LocalVariablesContainer &aLVC) const; + const Trk::TrackingVolume* processShield( const Trk::Volume*, int, std::string, LocalVariablesContainer &aLVC) const; + /** Private method to check volume properties */ + void checkVolume(const Trk::TrackingVolume*) const; + /** Private method to find detached volumes */ + std::vector<const Trk::DetachedTrackingVolume*>* getDetachedObjects(const Trk::Volume*, std::vector<const Trk::DetachedTrackingVolume*>&, LocalVariablesContainer &aLVC ,int mode=0) const; + /** Private method to check if constituent enclosed */ + bool enclosed(const Trk::Volume*, const Muon::Span*, LocalVariablesContainer &aLVC) const; + /** Private method to retrieve z partition */ + void getZParts(LocalVariablesContainer &aLVC) const; + /** Private method to retrieve phi partition */ + void getPhiParts(int, LocalVariablesContainer &aLVC) const; + /** Private method to retrieve h partition */ + void getHParts(LocalVariablesContainer &aLVC) const; + /** Private method to retrieve shield partition */ + void getShieldParts(LocalVariablesContainer & aLVC) const; + /** Private method to calculate volume */ + double calculateVolume(const Trk::Volume*) const; + /** Private method to blend the inert material */ + void blendMaterial(LocalVariablesContainer &aLVC) const; + + ToolHandle<Trk::IDetachedTrackingVolumeBuilder> m_stationBuilder{this,"MuonStationBuilder","Muon::MuonStationBuilder/MuonStationBuilder"}; //!< A Tool for station type creation + + ToolHandle<Trk::IDetachedTrackingVolumeBuilder> m_inertBuilder{this,"InertMaterialBuilder","Muon::MuonInertMaterialBuilder/MuonInertMaterialBuilder"}; //!< A Tool for inert object creation + + ToolHandle<Trk::ITrackingVolumeArrayCreator> m_trackingVolumeArrayCreator{this,"TrackingVolumeArrayCreator","Trk::TrackingVolumeArrayCreator/TrackingVolumeArrayCreator"}; //!< Helper Tool to create TrackingVolume Arrays + + ToolHandle<Trk::ITrackingVolumeHelper> m_trackingVolumeHelper{this,"TrackingVolumeHelper","Trk::TrackingVolumeHelper/TrackingVolumeHelper"}; //!< Helper Tool to create TrackingVolumes + + ServiceHandle<IEnvelopeDefSvc> m_enclosingEnvelopeSvc{this,"EnvelopeDefinitionSvc","AtlasEnvelopeDefSvc","n"}; //!< service to provide input volume size + + Gaudi::Property<bool> m_muonSimple{this,"SimpleMuonGeometry",false}; + Gaudi::Property<bool> m_loadMSentry{this,"LoadMSEntry",false}; + Gaudi::Property<bool> m_muonActive{this,"BuildActiveMaterial",true}; + Gaudi::Property<bool> m_muonInert{this,"BuildInertMaterial",true}; + + // Overall Dimensions + Gaudi::Property<double> m_innerBarrelRadius{this,"InnerBarrelRadius",4255.}; //!< minimal extend in radial dimension of the muon barrel + Gaudi::Property<double> m_outerBarrelRadius{this,"OuterBarrelRadius",13910.}; //!< maximal extend in radial dimension of the muon barrel + Gaudi::Property<double> m_barrelZ{this,"BarrelZ",6785.}; //!< maximal extend in z of the muon barrel + Gaudi::Property<double> m_innerEndcapZ{this,"InnerEndcapZ",12900.}; //!< maximal extend in z of the inner part of muon endcap + Gaudi::Property<double> m_outerEndcapZ{this,"OuterEndcapZ",26046.}; //!< maximal extend in z of the outer part of muon endcap + double m_bigWheel; //!< maximal extend in z of the big wheel + double m_outerWheel; //!< minimal extend in z of the outer wheel (EO) + double m_ectZ; //!< minimal extent in z of the ECT + double m_beamPipeRadius; + double m_innerShieldRadius; + double m_outerShieldRadius; + double m_diskShieldZ; + + Gaudi::Property<int> m_barrelEtaPartition{this,"EtaBarrelPartitions",9}; + Gaudi::Property<int> m_innerEndcapEtaPartition{this,"EtaInnerEndcapPartitions",3}; + Gaudi::Property<int> m_outerEndcapEtaPartition{this,"EtaOuterEndcapPartitions",3}; + Gaudi::Property<int> m_phiPartition{this,"PhiPartitions",16}; + + Gaudi::Property<bool> m_adjustStatic{this,"AdjustStatic",true}; + Gaudi::Property<bool> m_static3d{this,"StaticPartition3D",true}; + + Gaudi::Property<bool> m_blendInertMaterial{this,"BlendInertMaterial",false}; + Gaudi::Property<bool> m_removeBlended{this,"RemoveBlendedMaterialObjects",false}; + mutable std::atomic_uint m_inertPerm{0}; // number of perm objects + Gaudi::Property<double> m_alignTolerance{this,"AlignmentPositionTolerance",0.}; + Gaudi::Property<int> m_colorCode{this,"ColorCode",0}; + Gaudi::Property<int> m_activeAdjustLevel{this,"ActiveAdjustLevel",2}; + Gaudi::Property<int> m_inertAdjustLevel{this,"InertAdjustLevel",1}; + + mutable std::atomic_uint m_frameNum{0}; + mutable std::atomic_uint m_frameStat{0}; + + Gaudi::Property<std::string> m_entryVolume{this,"EntryVolumeName","MuonSpectrometerEntrance"}; + Gaudi::Property<std::string> m_exitVolume{this,"ExitVolumeName","All::Container::CompleteDetector"}; + + + const std::vector<const Trk::DetachedTrackingVolume*>* m_stations; // muon chambers + const std::vector<const Trk::DetachedTrackingVolume*>* m_inertObjs; // muon inert material + //mutable std::vector<std::pair<std::string,std::pair<double, unsigned int> > > m_dilFact; + //mutable std::vector<Trk::MaterialProperties> m_matProp; + typedef ServiceHandle<IChronoStatSvc> IChronoStatSvc_t; + IChronoStatSvc_t m_chronoStatSvc{this,"ChronoStatSvc","ChronoStatSvc","n"}; + }; + + +} // end of namespace + + +#endif //MUONTRACKINGGEOMETRY_MUONTRACKINGGEOMETRYBUILDER_H + + diff --git a/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/python/ConfiguredMuonTrackingGeometryBuilderCond.py b/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/python/ConfiguredMuonTrackingGeometryBuilderCond.py new file mode 100644 index 00000000000..0bbf301939a --- /dev/null +++ b/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/python/ConfiguredMuonTrackingGeometryBuilderCond.py @@ -0,0 +1,44 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + +##################################################### +# ConfiguredMuonTrackingGeometry module +# +# it inherits from MuonTrackingGeometryBuilder and performs +# standard configuration +# +###################################################### +# import the include statement +from AthenaCommon.Include import Include, IncludeError, include + +# import the configurable +from MuonTrackingGeometry.MuonTrackingGeometryConf import Muon__MuonTrackingGeometryBuilderCond + +# define the class +class ConfiguredMuonTrackingGeometryBuilderCond( Muon__MuonTrackingGeometryBuilderCond ): + # constructor + def __init__(self,name = 'MuonTrackingGeometryBuilderCond'): + + from TrkDetDescrSvc.TrkDetDescrJobProperties import TrkDetFlags + + # import the ToolSvc + from AthenaCommon.AppMgr import ToolSvc + if 'ToolSvc' not in dir() : + ToolSvc = ToolSvc() + + from MuonTrackingGeometry.MuonTrackingGeometryConf import Muon__MuonStationTypeBuilder + MuonStationTypeBuilder= Muon__MuonStationTypeBuilder(name = 'MuonStationTypeBuilder') + + ToolSvc += MuonStationTypeBuilder + + # muon active/passive geometry setup + from MuonTrackingGeometry.MuonTrackingGeometryConf import Muon__MuonStationBuilder + MuonStationBuilder= Muon__MuonStationBuilder(name = 'MuonStationBuilder' ) + ToolSvc += MuonStationBuilder + + from MuonTrackingGeometry.MuonTrackingGeometryConf import Muon__MuonInertMaterialBuilder + MuonInertMaterialBuilder= Muon__MuonInertMaterialBuilder(name = 'MuonInertMaterialBuilder') + ToolSvc += MuonInertMaterialBuilder + + Muon__MuonTrackingGeometryBuilderCond.__init__(self,name,\ + EntryVolumeName=TrkDetFlags.MuonSystemEntryVolumeName(),\ + ExitVolumeName = TrkDetFlags.MuonSystemContainerName()) diff --git a/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/python/ConfiguredMuonTrackingGeometryCond.py b/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/python/ConfiguredMuonTrackingGeometryCond.py new file mode 100644 index 00000000000..c3df82191aa --- /dev/null +++ b/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/python/ConfiguredMuonTrackingGeometryCond.py @@ -0,0 +1,30 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + + +from AthenaCommon.AppMgr import ToolSvc + +from TrkDetDescrSvc.TrkDetDescrJobProperties import TrkDetFlags + +from MuonTrackingGeometry.MuonTrackingGeometryConf import Muon__MuonStationTypeBuilder +MuonStationTypeBuilder= Muon__MuonStationTypeBuilder(name = 'MuonStationTypeBuilder') +ToolSvc += MuonStationTypeBuilder + +# muon active/passive geometry setup +from MuonTrackingGeometry.MuonTrackingGeometryConf import Muon__MuonStationBuilder +MuonStationBuilder= Muon__MuonStationBuilder(name = 'MuonStationBuilder') +MuonStationBuilder.StationTypeBuilder = MuonStationTypeBuilder +ToolSvc += MuonStationBuilder + +from MuonTrackingGeometry.MuonTrackingGeometryConf import Muon__MuonInertMaterialBuilder +MuonInertMaterialBuilder= Muon__MuonInertMaterialBuilder(name = 'MuonInertMaterialBuilder') +ToolSvc += MuonInertMaterialBuilder + +# muon tracking geometry builder +from MuonTrackingGeometry.MuonTrackingGeometryConf import Muon__MuonTrackingGeometryBuilderCond +MuonTrackingGeometryBuilderCond= Muon__MuonTrackingGeometryBuilderCond(name = 'MuonTrackingGeometryBuilderCond') +MuonTrackingGeometryBuilderCond.EntryVolumeName = TrkDetFlags.MuonSystemEntryVolumeName() +MuonTrackingGeometryBuilderCond.ExitVolumeName = TrkDetFlags.MuonSystemContainerName() +MuonTrackingGeometryBuilderCond.OutputLevel = TrkDetFlags.MuonBuildingOutputLevel() +ToolSvc += MuonTrackingGeometryBuilderCond + +#print MuonTrackingGeometryBuilder diff --git a/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/src/MuonTrackingGeometryBuilderCond.cxx b/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/src/MuonTrackingGeometryBuilderCond.cxx new file mode 100644 index 00000000000..4b4dfeb861e --- /dev/null +++ b/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/src/MuonTrackingGeometryBuilderCond.cxx @@ -0,0 +1,2655 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +////////////////////////////////////////////////////////////////// +// MuonTrackingGeometryBuilderCond.cxx, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +// Muon +#include "MuonTrackingGeometry/MuonTrackingGeometryBuilderCond.h" +#include "MuonReadoutGeometry/GlobalUtilities.h" +// Amg +#include "GeoPrimitives/GeoPrimitives.h" +// Units +#include "GaudiKernel/SystemOfUnits.h" +// Trk +#include "TrkDetDescrUtils/BinUtility.h" +#include "TrkDetDescrUtils/BinnedArray.h" +#include "TrkDetDescrUtils/BinnedArray1D.h" +#include "TrkDetDescrUtils/BinnedArray2D.h" +#include "TrkDetDescrUtils/BinnedArray1D1D1D.h" +#include "TrkDetDescrUtils/GeometryStatics.h" +#include "TrkDetDescrUtils/SharedObject.h" +#include "TrkVolumes/CylinderVolumeBounds.h" +#include "TrkVolumes/TrapezoidVolumeBounds.h" +#include "TrkVolumes/DoubleTrapezoidVolumeBounds.h" +#include "TrkVolumes/BevelledCylinderVolumeBounds.h" +#include "TrkVolumes/CuboidVolumeBounds.h" +#include "TrkVolumes/SubtractedVolumeBounds.h" +#include "TrkVolumes/CombinedVolumeBounds.h" +#include "TrkVolumes/SimplePolygonBrepVolumeBounds.h" +#include "TrkVolumes/PrismVolumeBounds.h" +#include "TrkVolumes/BoundarySurface.h" +#include "TrkGeometry/TrackingGeometry.h" +#include "TrkGeometry/TrackingVolume.h" +#include "TrkGeometry/GlueVolumesDescriptor.h" +#include "TrkGeometry/Material.h" +#include<fstream> + +// STD +#include <map> + + +// constructor +Muon::MuonTrackingGeometryBuilderCond::MuonTrackingGeometryBuilderCond(const std::string& t, const std::string& n, const IInterface* p) : + AthAlgTool(t,n,p), + m_bigWheel(15600.), + m_outerWheel(21000.), + m_ectZ(7920.), + m_beamPipeRadius(70.), + m_innerShieldRadius(850.), + m_outerShieldRadius(1500.), + m_diskShieldZ(6915.), + m_stations(0), + m_inertObjs(0) +{ + declareInterface<Trk::IGeometryBuilderCond>(this); +} + +// Athena standard methods +// initialize + +StatusCode Muon::MuonTrackingGeometryBuilderCond::initialize() +{ + + // Retrieve the tracking volume helper ------------------------------------------------- + if (m_trackingVolumeHelper.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool " << m_trackingVolumeHelper ); + return StatusCode::FAILURE; + } else + ATH_MSG_INFO( "Retrieved tool " << m_trackingVolumeHelper ); + + // Retrieve the tracking volume array creator ------------------------------------------- + if (m_trackingVolumeArrayCreator.retrieve().isFailure()) + { + ATH_MSG_FATAL( "Failed to retrieve tool " << m_trackingVolumeArrayCreator ); + return StatusCode::FAILURE; + } else + ATH_MSG_INFO( "Retrieved tool " << m_trackingVolumeArrayCreator ); + + // Retrieve the station builder (if configured) ------------------------------------------- + if (m_muonActive) { + + if (m_stationBuilder.retrieve().isFailure()) + { + ATH_MSG_ERROR( "Failed to retrieve tool " << m_stationBuilder <<" Creation of stations might fail." ); + } else + ATH_MSG_INFO( "Retrieved tool " << m_trackingVolumeArrayCreator ); + } else { + m_activeAdjustLevel = 0; // no active material to consider + } + + // Retrieve the inert material builder builder (if configured) ------------------------------------------- + + if (m_muonInert || m_blendInertMaterial) { + + if (m_inertBuilder.retrieve().isFailure()) + { + ATH_MSG_ERROR( "Failed to retrieve tool " << m_inertBuilder <<"Creation of inert material objects might fail." ); + } else + ATH_MSG_INFO( "Retrieved tool " << m_trackingVolumeArrayCreator ); + } + + if ( !m_muonInert ) m_inertAdjustLevel = 0; + + if (m_loadMSentry ) { + // retrieve envelope definition service -------------------------------------------------- + if ( m_enclosingEnvelopeSvc.retrieve().isFailure() ){ + ATH_MSG_WARNING( "Could not retrieve EnvelopeDefinition service. Using default definition."); + m_loadMSentry = false; + } + } + + // process muon material objects + if (m_muonActive && m_stationBuilder && !m_stations) m_stations = m_stationBuilder->buildDetachedTrackingVolumes(); + if (m_muonInert && m_inertBuilder && !m_inertObjs) m_inertObjs = m_inertBuilder->buildDetachedTrackingVolumes(m_blendInertMaterial); + + if (m_chronoStatSvc.retrieve().isFailure()) { + ATH_MSG_WARNING( "Could not retrieve Tool " << m_chronoStatSvc << ". Exiting."); + } + + + ATH_MSG_INFO( name() <<" initialize() successful" ); + + return StatusCode::SUCCESS; +} + + +std::pair<EventIDRange, const Trk::TrackingGeometry*> Muon::MuonTrackingGeometryBuilderCond::trackingGeometry(const EventContext& /*ctx*/, std::pair<EventIDRange, const Trk::TrackingVolume*> tVolPair) const +{ + ATH_MSG_INFO( name() <<" building tracking geometry" ); + m_chronoStatSvc->chronoStart("MS::build-up"); + //start with range from encapsulated TrackingGeometry if it exists, otherwise infinite range + //TODO/FIXME: this range must be intersected with IOV range of the Muon Tracking Geometry + EventIDRange range; + const Trk::TrackingVolume* tvol = nullptr; + if (tVolPair.second != nullptr){ + range = tVolPair.first; + tvol = tVolPair.second; + } + //load local variables to container + LocalVariablesContainer aLVC; + aLVC.m_innerBarrelRadius = m_innerBarrelRadius; + aLVC.m_outerBarrelRadius = m_outerBarrelRadius; + aLVC.m_innerEndcapZ = m_innerEndcapZ; + aLVC.m_outerEndcapZ = m_outerEndcapZ; + aLVC.m_adjustStatic = m_adjustStatic; + aLVC.m_static3d = m_static3d; + aLVC.m_blendMap.clear(); + aLVC.m_blendVols.clear(); + aLVC.m_stationSpan = 0; + aLVC.m_inertSpan = 0; + /////////////////////////////////////////////////////////////////////////////////////////////////// + // check setup + if (m_muonInert && m_blendInertMaterial) { + if (!aLVC.m_adjustStatic || !aLVC.m_static3d) { + ATH_MSG_INFO( name() <<" diluted inert material hardcoded for 3D volume frame, adjusting setup" ); + aLVC.m_adjustStatic = true; + aLVC.m_static3d = true; + } + } + + if (m_inertObjs && m_blendInertMaterial && m_removeBlended) { + while ( m_inertPerm<m_inertObjs->size() + && (*m_inertObjs)[m_inertPerm]->name().substr((*m_inertObjs)[m_inertPerm]->name().size()-4,4)=="PERM") m_inertPerm++; + } + + // find object's span with tolerance for the alignment + if (!aLVC.m_stationSpan) aLVC.m_stationSpan = findVolumesSpan(m_stations, 100.*m_alignTolerance, m_alignTolerance*Gaudi::Units::deg,aLVC); + if (!aLVC.m_inertSpan) aLVC.m_inertSpan = findVolumesSpan(m_inertObjs,0.,0.,aLVC); + + // 0) Preparation ////////////////////////////////////////////////////////////////////////////////////// + + aLVC.m_muonMaterial = Trk::Material(10e10,10e10,0.,0.,0.); // default material properties + + // dummy substructures + const Trk::LayerArray* dummyLayers = 0; + const Trk::TrackingVolumeArray* dummyVolumes = 0; + + + //////////////////////////////////////////////////////////////////////////////////////////////////////// + // Envelope definition (cutouts) + //////////////////////////////////////////////////////////////////////////////////////////////////////// + RZPairVector envelopeDefs; + if (m_enclosingEnvelopeSvc) { + // get the dimensions from the envelope service + RZPairVector& envelopeDefsIn = m_enclosingEnvelopeSvc->getMuonRZValues(); + + // find the max,max pair + unsigned int ii=0; + for (unsigned int i=0; i<envelopeDefsIn.size(); i++) { + if (envelopeDefsIn[i].second>envelopeDefsIn[ii].second) ii=i; + else if (envelopeDefsIn[i].second==envelopeDefsIn[ii].second && + envelopeDefsIn[i].first>envelopeDefsIn[ii].first) ii=i; + } + + // find the sense of rotation + int irot=1; + unsigned int inext=ii+1; + if (inext==envelopeDefsIn.size()) inext=0; + if (envelopeDefsIn[inext].second!=envelopeDefsIn[ii].second) {irot=-1; inext = ii>0 ? ii-1:envelopeDefsIn.size()-1 ;} + + // fill starting with upper low edge, end with upper high edge + if (irot>0) { + for (unsigned int i=inext; i<envelopeDefsIn.size(); i++) envelopeDefs.push_back(envelopeDefsIn[i]); + if (inext>0) for (unsigned int i=0; i<=inext-1; i++) envelopeDefs.push_back(envelopeDefsIn[i]); + } else { + int i=inext; while (i>=0) {envelopeDefs.push_back(envelopeDefsIn[i]); i=i-1;}; + inext = envelopeDefsIn.size()-1; while (inext>=ii) {envelopeDefs.push_back(envelopeDefsIn[inext]); inext=inext-1;}; + } + + // find maximal z,R extent + float maxR = 0.; + for (unsigned int i=0; i<envelopeDefs.size(); i++) { + if (envelopeDefs[i].first > maxR ) maxR = envelopeDefs[i].first; + } + + aLVC.m_outerBarrelRadius = maxR; + aLVC.m_outerEndcapZ = envelopeDefs[0].second; + + ATH_MSG_VERBOSE( "Muon envelope definition retrieved: outer R,Z:"<<aLVC.m_outerBarrelRadius<<","<< aLVC.m_outerEndcapZ ); + + // construct inner and outer envelope + + for (unsigned int i=0; i<envelopeDefs.size(); i++) { + ATH_MSG_VERBOSE( "Rz pair:"<< i<<":"<< envelopeDefs[i].first<<","<<envelopeDefs[i].second ); + } + + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + + if (m_muonSimple) { + Trk::VolumeBounds* globalBounds = new Trk::CylinderVolumeBounds(aLVC.m_outerBarrelRadius, + aLVC.m_outerEndcapZ); + Trk::TrackingVolume* topVolume = new Trk::TrackingVolume(0, + globalBounds, + aLVC.m_muonMaterial, + dummyLayers,dummyVolumes, + "GlobalVolume"); + aLVC.m_standaloneTrackingVolume = topVolume; + return std::make_pair(range, new Trk::TrackingGeometry(topVolume)); + } + + ATH_MSG_INFO( name() <<"building barrel+innerEndcap+outerEndcap" ); + +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// MuonSpectrometer contains: +// - Barrel +// - Endcaps inner/outer + const Trk::TrackingVolume* muonBarrel = 0; + Trk::CylinderVolumeBounds* barrelBounds = 0; + const Trk::TrackingVolume* negativeMuonOuterWheel = 0; + Trk::CylinderVolumeBounds* negativeOuterWheelBounds = 0; + const Trk::TrackingVolume* negativeMuonBigWheel = 0; + Trk::CylinderVolumeBounds* negativeBigWheelBounds = 0; + const Trk::TrackingVolume* negativeMuonOuterBuffer = 0; + Trk::CylinderVolumeBounds* negativeOuterBufferBounds = 0; + const Trk::TrackingVolume* positiveMuonOuterWheel = 0; + const Trk::TrackingVolume* negativeMuonSmallWheel = 0; + const Trk::TrackingVolume* positiveMuonSmallWheel = 0; + Trk::CylinderVolumeBounds* negativeSmallWheelBounds = 0; + const Trk::TrackingVolume* negativeECT = 0; + const Trk::TrackingVolume* positiveECT = 0; + Trk::CylinderVolumeBounds* negativeECTBounds = 0; + const Trk::TrackingVolume* positiveMuonBigWheel = 0; + const Trk::TrackingVolume* positiveMuonOuterBuffer = 0; +// volumes needed to close the geometry + const Trk::TrackingVolume* negBeamPipe = 0; + const Trk::TrackingVolume* posBeamPipe = 0; + Trk::CylinderVolumeBounds* negBeamPipeBounds = 0; + Trk::CylinderVolumeBounds* posBeamPipeBounds = 0; + const Trk::TrackingVolume* enclosed = 0; + Trk::CylinderVolumeBounds* enclosedBounds = 0; + const Trk::TrackingVolume* negDiskShield = 0; + Trk::CylinderVolumeBounds* negDiskShieldBounds = 0; + const Trk::TrackingVolume* posDiskShield = 0; + Trk::CylinderVolumeBounds* posDiskShieldBounds = 0; + const Trk::TrackingVolume* negInnerShield = 0; + const Trk::TrackingVolume* posInnerShield = 0; + Trk::CylinderVolumeBounds* negInnerShieldBounds = 0; + Trk::CylinderVolumeBounds* posInnerShieldBounds = 0; + const Trk::TrackingVolume* negOuterShield = 0; + const Trk::TrackingVolume* posOuterShield = 0; + Trk::CylinderVolumeBounds* negOuterShieldBounds = 0; + Trk::CylinderVolumeBounds* posOuterShieldBounds = 0; +// if input, redefine dimensions to fit expected MS entry + if (tvol){ + bool msEntryDefined = false; + if ( tvol->volumeName() == m_entryVolume ) msEntryDefined = true; + // get dimensions + ATH_MSG_DEBUG(" msEntryDefined " << msEntryDefined); + const Trk::CylinderVolumeBounds* enclosedDetectorBounds + = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(tvol->volumeBounds())); + if (!enclosedDetectorBounds) { + ATH_MSG_ERROR(" dynamic cast of enclosed volume to the cylinder bounds failed, aborting MTG build-up "); + return std::pair<EventIDRange, const Trk::TrackingGeometry*>(range, nullptr); + } + double enclosedDetectorHalfZ = enclosedDetectorBounds->halflengthZ(); + double enclosedDetectorOuterRadius = enclosedDetectorBounds->outerRadius(); + // get subvolumes at navigation level and check THEIR dimensions + const Trk::GlueVolumesDescriptor& enclosedDetGlueVolumes = tvol->glueVolumesDescriptor(); + std::vector<const Trk::TrackingVolume*> enclosedCentralFaceVolumes = enclosedDetGlueVolumes.glueVolumes(Trk::cylinderCover); + std::vector<const Trk::TrackingVolume*> enclosedNegativeFaceVolumes = enclosedDetGlueVolumes.glueVolumes(Trk::negativeFaceXY); + std::vector<const Trk::TrackingVolume*> enclosedPositiveFaceVolumes = enclosedDetGlueVolumes.glueVolumes(Trk::positiveFaceXY); + if (enclosedCentralFaceVolumes.size()) { + const Trk::CylinderVolumeBounds* cylR = dynamic_cast<const Trk::CylinderVolumeBounds*> (&(enclosedCentralFaceVolumes[0]->volumeBounds())); + if (cylR && cylR->outerRadius() != enclosedDetectorOuterRadius ) { + enclosedDetectorOuterRadius = cylR->outerRadius(); + ATH_MSG_WARNING(name() << " enclosed volume envelope outer radius does not correspond to radius of glue volumes : adjusted " ); + } + } + if (enclosedNegativeFaceVolumes.size() && enclosedPositiveFaceVolumes.size()) { + double negZ = -enclosedDetectorHalfZ; + double posZ = enclosedDetectorHalfZ; + const Trk::CylinderVolumeBounds* cylN = dynamic_cast<const Trk::CylinderVolumeBounds*> (&(enclosedNegativeFaceVolumes[0]->volumeBounds())); + if (cylN) negZ = enclosedNegativeFaceVolumes[0]->center()[2]-cylN->halflengthZ(); + const Trk::CylinderVolumeBounds* cylP = dynamic_cast<const Trk::CylinderVolumeBounds*> (&(enclosedPositiveFaceVolumes[0]->volumeBounds())); + if (cylP) posZ = enclosedPositiveFaceVolumes[0]->center()[2]+cylP->halflengthZ(); + if ( fabs(negZ+enclosedDetectorHalfZ)>0.001 || fabs(posZ-enclosedDetectorHalfZ)>0.001 ) { + ATH_MSG_WARNING( name() << " enclosed volume envelope z dimension does not correspond to that of glue volumes " ); + if ( fabs(negZ+posZ)<0.001) { + enclosedDetectorHalfZ = posZ; + ATH_MSG_WARNING( name() << " z adjusted " ); + } else { + ATH_MSG_ERROR( name() << "assymetric Z dimensions - cannot recover "<< negZ <<","<< posZ ); + return std::pair<EventIDRange, const Trk::TrackingGeometry*>(range, nullptr); + } + } + } + // + + + // + ATH_MSG_INFO( name() <<" dimensions of enclosed detectors (halfZ,outerR):" + << enclosedDetectorHalfZ<<","<< enclosedDetectorOuterRadius ); + // check if input makes sense - gives warning if cuts into muon envelope + // adjust radius + const Trk::TrackingVolume* barrelR = 0; + if ( enclosedDetectorOuterRadius > aLVC.m_innerBarrelRadius ) { + ATH_MSG_WARNING( name() <<" enclosed volume too wide, cuts into muon envelope, abandon :R:" <<enclosedDetectorOuterRadius ); + return std::pair<EventIDRange, const Trk::TrackingGeometry*>(range, nullptr); + } else { + aLVC.m_innerBarrelRadius = enclosedDetectorOuterRadius; + barrelR = tvol; + } + // adjust z + if ( enclosedDetectorHalfZ > m_barrelZ ) { + ATH_MSG_WARNING( name() <<" enclosed volume too long, cuts into muon envelope, abandon :Z:"<< enclosedDetectorHalfZ ); + return std::pair<EventIDRange, const Trk::TrackingGeometry*>(range, nullptr); + } else { + if ( enclosedDetectorHalfZ < m_barrelZ ) { + Trk::CylinderVolumeBounds* barrelZPBounds = new Trk::CylinderVolumeBounds(aLVC.m_innerBarrelRadius, + 0.5*(m_barrelZ - enclosedDetectorHalfZ) ); + Trk::CylinderVolumeBounds* barrelZMBounds = new Trk::CylinderVolumeBounds(aLVC.m_innerBarrelRadius, + 0.5*(m_barrelZ - enclosedDetectorHalfZ) ); + double zbShift = 0.5*(m_barrelZ + enclosedDetectorHalfZ); + const Trk::TrackingVolume* barrelZPBuffer = new Trk::TrackingVolume(new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,zbShift))), + barrelZPBounds, + aLVC.m_muonMaterial, + dummyLayers,dummyVolumes, + "BarrelRZPosBuffer"); + const Trk::TrackingVolume* barrelZMBuffer = new Trk::TrackingVolume(new Amg::Transform3D(Amg::Translation3D(Amg::Vector3D(0.,0.,-zbShift))), + barrelZMBounds, + aLVC.m_muonMaterial, + dummyLayers,dummyVolumes, + "BarrelRZNegBuffer"); + + ATH_MSG_INFO( name() << "glue barrel R + barrel Z buffer" ); + const Trk::TrackingVolume* barrelZP = m_trackingVolumeHelper->glueTrackingVolumeArrays(*barrelR, Trk::positiveFaceXY, + *barrelZPBuffer,Trk::negativeFaceXY, + "All::Gaps::BarrelZP"); + // set name + std::string nameEncl = msEntryDefined ? "All::Gaps::Barrel" : m_entryVolume ; + ATH_MSG_DEBUG( " nameEncl " << nameEncl); + enclosed = m_trackingVolumeHelper->glueTrackingVolumeArrays(*barrelZP, Trk::negativeFaceXY, + *barrelZMBuffer,Trk::positiveFaceXY, + nameEncl); + + } else enclosed = barrelR; + // ST the following simplification forces MuonSpectrometerEntrance to coincide with Calo::Container + //m_barrelZ = enclosedDetectorHalfZ; + //enclosed = barrelR; + } + + } else { // no input, create the enclosed volume + if (m_loadMSentry && m_enclosingEnvelopeSvc ) { + RZPairVector& envelopeDefs = m_enclosingEnvelopeSvc->getCaloRZValues(); + // to be implemented in detail - for the moment, take just maximal extent + ATH_MSG_DEBUG( " m_loadMSentry " << m_loadMSentry << " m_enclosingEnvelopeSvc " << m_enclosingEnvelopeSvc ); + double rmax = 0.; double zmax = 0.; + for (unsigned int i=0; i<envelopeDefs.size(); i++) { + if ( envelopeDefs[i].first>rmax ) rmax= envelopeDefs[i].first; + if ( fabs(envelopeDefs[i].second)>zmax ) zmax= fabs(envelopeDefs[i].second); + } + if (envelopeDefs.size()) { + if ( rmax>0. && rmax <= aLVC.m_innerBarrelRadius && zmax>0. && zmax <= m_barrelZ ) { + enclosedBounds = new Trk::CylinderVolumeBounds(rmax,zmax); + } else { + ATH_MSG_INFO( name() << " input MSEntrance size (R,Z:"<< rmax <<","<<zmax<<") clashes with MS material, switch to default values (R,Z:" << aLVC.m_innerBarrelRadius <<","<< m_barrelZ << ")" ); + } + } + } + + if (!enclosedBounds) enclosedBounds = new Trk::CylinderVolumeBounds(aLVC.m_innerBarrelRadius, + m_barrelZ); + enclosed = new Trk::TrackingVolume(0, + enclosedBounds, + aLVC.m_muonMaterial, + dummyLayers,dummyVolumes, + m_entryVolume); + enclosed->registerColorCode(0); + ATH_MSG_DEBUG( " register Barrel m_entryVolume " << m_entryVolume); + } + + // construct inner and outer envelope + + for (unsigned int i=0; i<envelopeDefs.size(); i++) { + //ATH_MSG_VERBOSE( "Rz pair:"<< i<<":"<< envelopeDefs[i].first<<","<<envelopeDefs[i].second ); + if (aLVC.m_msCutoutsIn.size() && aLVC.m_msCutoutsIn.back().second== -aLVC.m_outerEndcapZ) break; + if ( !aLVC.m_msCutoutsIn.size() || fabs(aLVC.m_msCutoutsIn.back().second) > m_barrelZ + || fabs(envelopeDefs[i].second)> m_barrelZ ) aLVC.m_msCutoutsIn.push_back(envelopeDefs[i]); + else if (aLVC.m_msCutoutsIn.size() && aLVC.m_msCutoutsIn.back().second==m_barrelZ && aLVC.m_msCutoutsIn.back().first!=aLVC.m_innerBarrelRadius) { + aLVC.m_msCutoutsIn.push_back(RZPair(aLVC.m_innerBarrelRadius,m_barrelZ)); + aLVC.m_msCutoutsIn.push_back(RZPair(aLVC.m_innerBarrelRadius,-m_barrelZ)); + aLVC.m_msCutoutsIn.push_back(RZPair(aLVC.m_msCutoutsIn[aLVC.m_msCutoutsIn.size()-3].first,-m_barrelZ)); + } + } + + unsigned int il=1; + while (envelopeDefs[il-1].second!=-aLVC.m_outerEndcapZ) il++; + for ( ; il<envelopeDefs.size(); il++) aLVC.m_msCutoutsOut.push_back(envelopeDefs[il]); + + for (unsigned int i=0; i<aLVC.m_msCutoutsIn.size(); i++) { + ATH_MSG_VERBOSE( "Rz pair for inner MS envelope:"<< i<<":"<< aLVC.m_msCutoutsIn[i].first<<","<<aLVC.m_msCutoutsIn[i].second ); + } + for (unsigned int i=0; i<aLVC.m_msCutoutsOut.size(); i++) { + ATH_MSG_VERBOSE( "Rz pair for outer MS envelope:"<< i<<":"<< aLVC.m_msCutoutsOut[i].first<<","<<aLVC.m_msCutoutsOut[i].second ); + } + + if ( aLVC.m_msCutoutsIn[5].second != aLVC.m_innerEndcapZ) { + aLVC.m_innerEndcapZ = aLVC.m_msCutoutsIn[5].second; + } + ATH_MSG_VERBOSE( "inner endcap Z set to:"<< aLVC.m_innerEndcapZ ); + + // create central volume ("enclosed" + disk shields ) - this is to allow safe gluing with 3D MS binning + getShieldParts(aLVC); + + negDiskShieldBounds = new Trk::CylinderVolumeBounds(aLVC.m_innerBarrelRadius, + 0.5*(m_diskShieldZ - m_barrelZ) ); + Amg::Vector3D negDiskShieldPosition(0.,0.,-0.5*(m_diskShieldZ+m_barrelZ)); + Trk::Volume negDiskVol(new Amg::Transform3D(Amg::Translation3D(negDiskShieldPosition)),negDiskShieldBounds); + negDiskShield = processShield(&negDiskVol,2,"Muons::Detectors::NegativeDiskShield",aLVC); + + posDiskShieldBounds = new Trk::CylinderVolumeBounds(aLVC.m_innerBarrelRadius, + 0.5*(m_diskShieldZ - m_barrelZ) ); + Amg::Vector3D posDiskShieldPosition(0.,0., 0.5*(m_diskShieldZ+m_barrelZ)); + Trk::Volume posDiskVol(new Amg::Transform3D(Amg::Translation3D(posDiskShieldPosition)),posDiskShieldBounds); + posDiskShield = processShield(&posDiskVol,2,"Muons::Detectors::PositiveDiskShield",aLVC); + + ATH_MSG_INFO( name() << "glue enclosed + disk shields" ); + const Trk::TrackingVolume* centralP = m_trackingVolumeHelper->glueTrackingVolumeArrays(*enclosed, Trk::positiveFaceXY, + *posDiskShield,Trk::negativeFaceXY, + "Muon::Container::CentralP"); + const Trk::TrackingVolume* central = m_trackingVolumeHelper->glueTrackingVolumeArrays(*centralP, Trk::negativeFaceXY, + *negDiskShield,Trk::positiveFaceXY, + "Muon::Container::Central"); + +// define basic volumes + if (aLVC.m_adjustStatic) { getZParts(aLVC); getHParts(aLVC);} + +// muon barrel + barrelBounds = new Trk::CylinderVolumeBounds(aLVC.m_innerBarrelRadius, + aLVC.m_outerBarrelRadius, + m_diskShieldZ); + Trk::Volume barrelVol(0,barrelBounds); +// process volume +// barrel + if (aLVC.m_adjustStatic && aLVC.m_static3d) muonBarrel = processVolume( &barrelVol,0,"Muon::Detectors::Barrel",aLVC); + else if (aLVC.m_adjustStatic) muonBarrel = processVolume( &barrelVol,-1,"Muon::Detectors::Barrel",aLVC); + else muonBarrel = processVolume( &barrelVol,m_barrelEtaPartition,m_phiPartition,"Muon::Detectors::Barrel",aLVC); +// inner Endcap +// build as smallWheel+ECT +// small wheel + double smallWheelZHalfSize = 0.5*(m_ectZ - m_diskShieldZ); + negativeSmallWheelBounds = new Trk::CylinderVolumeBounds(m_innerShieldRadius, + aLVC.m_outerBarrelRadius, + smallWheelZHalfSize); + Amg::Vector3D negSmallWheelPosition(0.,0.,-m_ectZ+smallWheelZHalfSize); + Amg::Transform3D* negSmallWheelTransf = new Amg::Transform3D(Amg::Translation3D(negSmallWheelPosition)); + Trk::Volume negSWVol(negSmallWheelTransf,negativeSmallWheelBounds); + if (aLVC.m_adjustStatic && aLVC.m_static3d) negativeMuonSmallWheel = processVolume( &negSWVol,1,"Muon::Detectors::NegativeSmallWheel",aLVC ); + else if (aLVC.m_adjustStatic) negativeMuonSmallWheel = processVolume( &negSWVol,-1,"Muon::Detectors::NegativeSmallWheel" ,aLVC); + else negativeMuonSmallWheel = processVolume( &negSWVol,m_innerEndcapEtaPartition,m_phiPartition, + "Muon::Detectors::NegativeSmallWheel" ,aLVC); + //checkVolume(negativeMuonSmallWheel); + // + Amg::Vector3D posSmallWheelShift(0.,0.,2*(m_ectZ-smallWheelZHalfSize)); + Trk::Volume posSWVol(negSWVol,Amg::Transform3D(Amg::Translation3D(posSmallWheelShift))); + if (aLVC.m_adjustStatic && aLVC.m_static3d) positiveMuonSmallWheel = processVolume( &posSWVol,1,"Muon::Detectors::PositiveSmallWheel" ,aLVC); + else if (aLVC.m_adjustStatic) positiveMuonSmallWheel = processVolume( &posSWVol,-1,"Muon::Detectors::PositiveSmallWheel" ,aLVC); + else positiveMuonSmallWheel = processVolume( &posSWVol,m_innerEndcapEtaPartition,m_phiPartition, + "Muon::Detectors::PositiveSmallWheel" ,aLVC); + //checkVolume(positiveMuonSmallWheel); +// ECT + double ectZHalfSize = 0.5*(aLVC.m_innerEndcapZ - m_ectZ); + negativeECTBounds = new Trk::CylinderVolumeBounds(m_innerShieldRadius, + aLVC.m_outerBarrelRadius, + ectZHalfSize); + Amg::Vector3D negECTPosition(0.,0.,-m_ectZ-ectZHalfSize); + Amg::Transform3D* negECTTransf = new Amg::Transform3D(Amg::Translation3D(negECTPosition)); + Trk::Volume negECTVol(negECTTransf,negativeECTBounds); + if (aLVC.m_adjustStatic && aLVC.m_static3d) negativeECT = processVolume( &negECTVol,2,"Muon::Detectors::NegativeECT" ,aLVC); + else if (aLVC.m_adjustStatic) negativeECT = processVolume( &negECTVol,-1,"Muon::Detectors::NegativeECT" ,aLVC); + else negativeECT = processVolume( &negECTVol,m_innerEndcapEtaPartition,m_phiPartition, + "Muon::Detectors::NegativeECT" ,aLVC); + //checkVolume(negativeECT); + // + Amg::Vector3D posECTShift(0.,0.,2*(m_ectZ+ectZHalfSize)); + Trk::Volume posECTVol(negECTVol,Amg::Transform3D(Amg::Translation3D(posECTShift))); + if (aLVC.m_adjustStatic && m_static3d) positiveECT = processVolume( &posECTVol,2,"Muon::Detectors::PositiveECT" ,aLVC); + else if (aLVC.m_adjustStatic) positiveECT = processVolume( &posECTVol,-1,"Muon::Detectors::PositiveECT" ,aLVC); + else positiveECT = processVolume( &posECTVol,m_innerEndcapEtaPartition,m_phiPartition, + "Muon::Detectors::PositiveECT" ,aLVC); + //checkVolume(positiveECT); + // glue + const Trk::TrackingVolume* negativeMuonInnerEndcap = + m_trackingVolumeHelper->glueTrackingVolumeArrays(*negativeECT, Trk::positiveFaceXY, + *negativeMuonSmallWheel, Trk::negativeFaceXY, + "Muon::Container::NegInnerEndcap"); + const Trk::TrackingVolume* positiveMuonInnerEndcap = + m_trackingVolumeHelper->glueTrackingVolumeArrays(*positiveMuonSmallWheel, Trk::positiveFaceXY, + *positiveECT, Trk::negativeFaceXY, + "Muon::Container::PosInnerEndcap"); + +// inner shields + double innerEndcapZHalfSize = 0.5*(aLVC.m_innerEndcapZ - m_diskShieldZ); + negInnerShieldBounds = new Trk::CylinderVolumeBounds(m_beamPipeRadius, + m_innerShieldRadius, + innerEndcapZHalfSize); + Amg::Vector3D negInnerEndcapPosition(0.,0.,-m_diskShieldZ-innerEndcapZHalfSize); + Trk::Volume negisVol(new Amg::Transform3D(Amg::Translation3D(negInnerEndcapPosition)),negInnerShieldBounds); + negInnerShield = processShield(&negisVol,1,"Muons::Detectors::NegativeInnerShield",aLVC); + + posInnerShieldBounds = new Trk::CylinderVolumeBounds(m_beamPipeRadius, + m_innerShieldRadius, + innerEndcapZHalfSize); + Amg::Vector3D posInnerEndcapPosition(0.,0.,m_diskShieldZ+innerEndcapZHalfSize); + Trk::Volume posisVol(new Amg::Transform3D(Amg::Translation3D(posInnerEndcapPosition)),posInnerShieldBounds); + posInnerShield = processShield(&posisVol,1,"Muons::Detectors::PositiveInnerShield",aLVC); + +// outer Endcap +// build as bigWheel+buffer+outerWheel +// outer wheel + double outerWheelZHalfSize = 0.5*(aLVC.m_outerEndcapZ - m_outerWheel); + negativeOuterWheelBounds = new Trk::CylinderVolumeBounds(m_outerShieldRadius, + aLVC.m_outerBarrelRadius, + outerWheelZHalfSize); + Amg::Vector3D negOuterWheelPosition(0.,0.,-aLVC.m_outerEndcapZ+outerWheelZHalfSize); + Amg::Transform3D* negOuterWheelTransf = new Amg::Transform3D(Amg::Translation3D(negOuterWheelPosition)); + Trk::Volume negOWVol(negOuterWheelTransf,negativeOuterWheelBounds); + if (aLVC.m_adjustStatic && aLVC.m_static3d) negativeMuonOuterWheel = processVolume( &negOWVol,3,"Muon::Detectors::NegativeOuterWheel" ,aLVC); + else if (aLVC.m_adjustStatic) negativeMuonOuterWheel = processVolume( &negOWVol,-1,"Muon::Detectors::NegativeOuterWheel" ,aLVC); + else negativeMuonOuterWheel = processVolume( &negOWVol,m_outerEndcapEtaPartition,m_phiPartition, + "Muon::Detectors::NegativeOuterWheel" ,aLVC); + // + Amg::Vector3D posOuterWheelShift(0.,0.,2*(aLVC.m_outerEndcapZ-outerWheelZHalfSize)); + Trk::Volume posOWVol(negOWVol,Amg::Transform3D(Amg::Translation3D(posOuterWheelShift))); + if (aLVC.m_adjustStatic && aLVC.m_static3d) positiveMuonOuterWheel = processVolume( &posOWVol,3,"Muon::Detectors::PositiveOuterWheel" ,aLVC); + else if (aLVC.m_adjustStatic) positiveMuonOuterWheel = processVolume( &posOWVol,-1,"Muon::Detectors::PositiveOuterWheel" ,aLVC); + else positiveMuonOuterWheel = processVolume( &posOWVol,m_outerEndcapEtaPartition,m_phiPartition, + "Muon::Detectors::PositiveOuterWheel" ,aLVC); +// outer buffer + double outerBufferZHalfSize = 0.5*(m_outerWheel - m_bigWheel); + negativeOuterBufferBounds = new Trk::CylinderVolumeBounds(m_outerShieldRadius, + aLVC.m_outerBarrelRadius, + outerBufferZHalfSize); + Amg::Vector3D negOuterBufferPosition(0.,0.,-m_bigWheel-outerBufferZHalfSize); + Amg::Transform3D* negOuterBufferTransf = new Amg::Transform3D(Amg::Translation3D(negOuterBufferPosition)); + Trk::Volume negBuffVol(negOuterBufferTransf,negativeOuterBufferBounds); + if (aLVC.m_adjustStatic && aLVC.m_static3d) negativeMuonOuterBuffer = processVolume( &negBuffVol,3,"Muon::Detectors::NegativeOuterBuffer" ,aLVC); + else if (aLVC.m_adjustStatic) negativeMuonOuterBuffer = processVolume( &negBuffVol,-1,"Muon::Detectors::NegativeOuterBuffer" ,aLVC); + else negativeMuonOuterBuffer = processVolume( &negBuffVol,m_outerEndcapEtaPartition,m_phiPartition, + "Muon::Detectors::NegativeOuterBuffer" ,aLVC); + // + Amg::Vector3D posOuterBufferShift(0.,0.,2*(m_bigWheel+outerBufferZHalfSize)); + Trk::Volume posBuffVol(negBuffVol,Amg::Transform3D(Amg::Translation3D(posOuterBufferShift))); + if (aLVC.m_adjustStatic && aLVC.m_static3d) positiveMuonOuterBuffer = processVolume( &posBuffVol,3,"Muon::Detectors::PositiveOuterBuffer" ,aLVC); + else if (aLVC.m_adjustStatic) positiveMuonOuterBuffer = processVolume( &posBuffVol,-1,"Muon::Detectors::PositiveOuterBuffer" ,aLVC); + else positiveMuonOuterBuffer = processVolume( &posBuffVol,m_outerEndcapEtaPartition,m_phiPartition, + "Muon::Detectors::PositiveOuterBuffer" ,aLVC); +// big wheel + double bigWheelZHalfSize = 0.5*(m_bigWheel - aLVC.m_innerEndcapZ); + negativeBigWheelBounds = new Trk::CylinderVolumeBounds(m_outerShieldRadius, + aLVC.m_outerBarrelRadius, + bigWheelZHalfSize); + Amg::Vector3D negBigWheelPosition(0.,0.,-aLVC.m_innerEndcapZ-bigWheelZHalfSize); + Amg::Transform3D* negBigWheelTransf = new Amg::Transform3D(Amg::Translation3D(negBigWheelPosition)); + Trk::Volume negBWVol(negBigWheelTransf,negativeBigWheelBounds); + if (aLVC.m_adjustStatic && aLVC.m_static3d) negativeMuonBigWheel = processVolume( &negBWVol,3,"Muon::Detectors::NegativeBigWheel" ,aLVC); + else if (aLVC.m_adjustStatic) negativeMuonBigWheel = processVolume( &negBWVol,-1,"Muon::Detectors::NegativeBigWheel" ,aLVC); + else negativeMuonBigWheel = processVolume( &negBWVol,m_outerEndcapEtaPartition,m_phiPartition, + "Muon::Detectors::NegativeBigWheel" ,aLVC); + // + Amg::Vector3D posBigWheelShift(0.,0.,2*(aLVC.m_innerEndcapZ+bigWheelZHalfSize)); + Trk::Volume posBWVol(negBWVol,Amg::Transform3D(Amg::Translation3D(posBigWheelShift))); + if (aLVC.m_adjustStatic && aLVC.m_static3d) positiveMuonBigWheel = processVolume( &posBWVol,3,"Muon::Detectors::PositiveBigWheel" ,aLVC); + else if (aLVC.m_adjustStatic) positiveMuonBigWheel = processVolume( &posBWVol,-1,"Muon::Detectors::PositiveBigWheel" ,aLVC); + else positiveMuonBigWheel = processVolume( &posBWVol,m_outerEndcapEtaPartition,m_phiPartition, + "Muon::Detectors::PositiveBigWheel" ,aLVC); +// glue + const Trk::TrackingVolume* negNavOEndcap = m_trackingVolumeHelper->glueTrackingVolumeArrays(*negativeMuonOuterWheel, Trk::positiveFaceXY, + *negativeMuonOuterBuffer, Trk::negativeFaceXY, + "Muon::Container::NegOEndcap"); + const Trk::TrackingVolume* posNavOEndcap = m_trackingVolumeHelper->glueTrackingVolumeArrays(*positiveMuonOuterBuffer, Trk::positiveFaceXY, + *positiveMuonOuterWheel, Trk::negativeFaceXY, + "Muon::Container::PosOEndcap"); + const Trk::TrackingVolume* negativeMuonOuterEndcap = + m_trackingVolumeHelper->glueTrackingVolumeArrays(*negNavOEndcap, Trk::positiveFaceXY, + *negativeMuonBigWheel, Trk::negativeFaceXY, + "Muon::Container::NegOuterEndcap"); + const Trk::TrackingVolume* positiveMuonOuterEndcap = + m_trackingVolumeHelper->glueTrackingVolumeArrays(*positiveMuonBigWheel, Trk::positiveFaceXY, + *posNavOEndcap, Trk::negativeFaceXY, + "Muon::Container::PosOuterEndcap"); + +// outer shields + double outerEndcapZHalfSize = 0.5*(aLVC.m_outerEndcapZ-aLVC.m_innerEndcapZ); + double outerEndcapPosition = 0.5*(aLVC.m_outerEndcapZ+aLVC.m_innerEndcapZ); + Amg::Vector3D negOuterShieldPosition(0.,0.,-outerEndcapPosition); + negOuterShieldBounds = new Trk::CylinderVolumeBounds(m_beamPipeRadius, + m_outerShieldRadius, + outerEndcapZHalfSize); + Trk::Volume negosVol(new Amg::Transform3D(Amg::Translation3D(negOuterShieldPosition)),negOuterShieldBounds); + negOuterShield = processShield(&negosVol,0,"Muons::Detectors::NegativeOuterShield",aLVC); + + posOuterShieldBounds = new Trk::CylinderVolumeBounds(m_beamPipeRadius, + m_outerShieldRadius, + outerEndcapZHalfSize); + Amg::Vector3D posOuterShieldPosition(0.,0.,outerEndcapPosition); + Trk::Volume pososVol(new Amg::Transform3D(Amg::Translation3D(posOuterShieldPosition)),posOuterShieldBounds); + posOuterShield = processShield(&pososVol,0,"Muons::Detectors::PositiveOuterShield",aLVC); + +// beamPipe + negBeamPipeBounds = new Trk::CylinderVolumeBounds(m_beamPipeRadius, + outerEndcapZHalfSize+innerEndcapZHalfSize); + posBeamPipeBounds = new Trk::CylinderVolumeBounds(m_beamPipeRadius, + outerEndcapZHalfSize+innerEndcapZHalfSize); + Amg::Vector3D posBeamPipePosition(0.,0., aLVC.m_outerEndcapZ-innerEndcapZHalfSize-outerEndcapZHalfSize); + Amg::Vector3D negBeamPipePosition(0.,0.,-aLVC.m_outerEndcapZ+innerEndcapZHalfSize+outerEndcapZHalfSize); + Trk::Volume negbpVol(new Amg::Transform3D(Amg::Translation3D(negBeamPipePosition)),negBeamPipeBounds); + negBeamPipe = processVolume(&negbpVol,1,1,"Muons::Gaps::NegativeBeamPipe",aLVC); + Trk::Volume posbpVol(new Amg::Transform3D(Amg::Translation3D(posBeamPipePosition)),posBeamPipeBounds); + posBeamPipe = processVolume(&posbpVol,1,1,"Muons::Gaps::PositiveBeamPipe",aLVC); + + negBeamPipe->registerColorCode(0); + posBeamPipe->registerColorCode(0); + + ATH_MSG_INFO( name() <<" volumes defined " ); +// +// glue volumes at navigation level, create enveloping volume +// radially +// central + barrel + ATH_MSG_INFO( name() << "glue barrel+enclosed volumes" ); + const Trk::TrackingVolume* barrel = m_trackingVolumeHelper->glueTrackingVolumeArrays(*muonBarrel,Trk::tubeInnerCover, + *central, Trk::cylinderCover, + "All::Container::Barrel"); + //checkVolume(barrel); +// shield+outerEndcap + ATH_MSG_INFO( name() << "glue shield+outerEndcap" ); + const Trk::TrackingVolume* negOuterEndcap = m_trackingVolumeHelper->glueTrackingVolumeArrays(*negativeMuonOuterEndcap, Trk::tubeInnerCover, + *negOuterShield, Trk::tubeOuterCover, + "Muon::Container::NegativeOuterEndcap"); + //checkVolume(negOuterEndcap); + const Trk::TrackingVolume* posOuterEndcap = m_trackingVolumeHelper->glueTrackingVolumeArrays(*positiveMuonOuterEndcap, Trk::tubeInnerCover, + *posOuterShield,Trk::tubeOuterCover, + "Muon::Container::PositiveOuterEndcap"); + //checkVolume(posOuterEndcap); +// shield+innerEndcap + ATH_MSG_INFO( name() << "glue shield+innerEndcap" ); + const Trk::TrackingVolume* negInnerEndcap = m_trackingVolumeHelper->glueTrackingVolumeArrays(*negativeMuonInnerEndcap, Trk::tubeInnerCover, + *negInnerShield, Trk::tubeOuterCover, + "Muon::Container::NegativeInnerEndcap"); + //checkVolume(negInnerEndcap); + const Trk::TrackingVolume* posInnerEndcap = m_trackingVolumeHelper->glueTrackingVolumeArrays(*positiveMuonInnerEndcap, Trk::tubeInnerCover, + *posInnerShield,Trk::tubeOuterCover, + "Muon::Container::PositiveInnerEndcap"); + //checkVolume(posInnerEndcap); +// inner+outerEndcap + ATH_MSG_INFO( name() << "glue inner+outerEndcap" ); + const Trk::TrackingVolume* negNavEndcap = m_trackingVolumeHelper->glueTrackingVolumeArrays(*negOuterEndcap, Trk::positiveFaceXY, + *negInnerEndcap, Trk::negativeFaceXY, + "Muon::Container::NegativeEndcap"); + const Trk::TrackingVolume* posNavEndcap = m_trackingVolumeHelper->glueTrackingVolumeArrays(*posInnerEndcap, Trk::positiveFaceXY, + *posOuterEndcap, Trk::negativeFaceXY, + "Muon::Container::PositiveEndcap"); + //checkVolume(negNavEndcap); + //checkVolume(posNavEndcap); +// beam pipe + endcaps + ATH_MSG_INFO( name() << "glue beamPipe+endcaps" ); + const Trk::TrackingVolume* negEndcap = m_trackingVolumeHelper->glueTrackingVolumeArrays(*negNavEndcap, Trk::tubeInnerCover, + *negBeamPipe, Trk::cylinderCover, + "All::Container::NegativeEndcap"); + const Trk::TrackingVolume* posEndcap = m_trackingVolumeHelper->glueTrackingVolumeArrays(*posNavEndcap, Trk::tubeInnerCover, + *posBeamPipe, Trk::cylinderCover, + "All::Container::PositiveEndcap"); + //checkVolume(negEndcap); + //checkVolume(posEndcap); +// barrel + endcaps + ATH_MSG_INFO( name() << "glue barrel+endcaps" ); + + const Trk::TrackingVolume* negDet = m_trackingVolumeHelper->glueTrackingVolumeArrays(*negEndcap, Trk::positiveFaceXY, + *barrel, Trk::negativeFaceXY, + "All::Container::NegDet"); + const Trk::TrackingVolume* detector = m_trackingVolumeHelper->glueTrackingVolumeArrays(*posEndcap, Trk::negativeFaceXY, + *negDet, Trk::positiveFaceXY, + m_exitVolume); +// blend material + if (m_blendInertMaterial) blendMaterial(aLVC); + +// tracking geometry + Trk::TrackingGeometry* trackingGeometry = new Trk::TrackingGeometry(detector,Trk::globalSearch); + +// clean-up + if (aLVC.m_stationSpan) { + for (size_t i = 0; i < aLVC.m_stationSpan->size(); i++) + delete (*aLVC.m_stationSpan)[i]; + delete aLVC.m_stationSpan; aLVC.m_stationSpan = 0; + } + if (aLVC.m_inertSpan) { + for (size_t i = 0; i < aLVC.m_inertSpan->size(); i++) + delete (*aLVC.m_inertSpan)[i]; + delete aLVC.m_inertSpan; aLVC.m_inertSpan = 0; + } + + for (size_t i = 0; i < aLVC.m_spans.size(); i++) delete aLVC.m_spans[i]; + + for (std::map<const Trk::DetachedTrackingVolume*,std::vector<const Trk::TrackingVolume*>* >::iterator it = aLVC.m_blendMap.begin(); + it != aLVC.m_blendMap.end(); + ++it) + { + delete it->second; + } + + m_chronoStatSvc->chronoStop("MS::build-up"); + + ATH_MSG_INFO( name() <<" returning tracking geometry " ); + ATH_MSG_INFO( name() <<" with "<< m_frameNum<<" subvolumes at navigation level" ); + ATH_MSG_INFO( name() <<"( mean number of enclosed detached volumes:"<< float(m_frameStat)/m_frameNum<<")" ); + return std::make_pair(range, trackingGeometry); +} + +// finalize +StatusCode Muon::MuonTrackingGeometryBuilderCond::finalize() +{ + if (m_stations) { + for (size_t i = 0; i < m_stations->size(); i++) { + if ((*m_stations)[i]) delete (*m_stations)[i]; + else ATH_MSG_DEBUG( name() << " station pointer corrupted ! " ); + } + delete m_stations; m_stations = 0; + } + if (m_inertObjs) { + unsigned int inLim = (m_blendInertMaterial && m_removeBlended) ? (unsigned int)m_inertPerm : m_inertObjs->size(); + for (size_t i = 0; i < inLim; i++) { + if ((*m_inertObjs)[i]) delete (*m_inertObjs)[i]; + else ATH_MSG_DEBUG( name() << " inert object pointer corrupted ! " ); + } + delete m_inertObjs; m_inertObjs = 0; + } + + m_chronoStatSvc->chronoPrint("MS::build-up"); + + ATH_MSG_INFO( name() <<" finalize() successful" ); + return StatusCode::SUCCESS; +} +const Muon::Span* Muon::MuonTrackingGeometryBuilderCond::findVolumeSpan(const Trk::VolumeBounds* volBounds, Amg::Transform3D transform, double zTol, double phiTol, LocalVariablesContainer &aLVC) const +{ + if (!volBounds) return 0; + // volume shape + const Trk::CuboidVolumeBounds* box = dynamic_cast<const Trk::CuboidVolumeBounds*> (volBounds); + const Trk::TrapezoidVolumeBounds* trd = dynamic_cast<const Trk::TrapezoidVolumeBounds*> (volBounds); + const Trk::DoubleTrapezoidVolumeBounds* dtrd = dynamic_cast<const Trk::DoubleTrapezoidVolumeBounds*> (volBounds); + const Trk::BevelledCylinderVolumeBounds* bcyl = dynamic_cast<const Trk::BevelledCylinderVolumeBounds*> (volBounds); + const Trk::CylinderVolumeBounds* cyl = dynamic_cast<const Trk::CylinderVolumeBounds*> (volBounds); + const Trk::SubtractedVolumeBounds* sub = dynamic_cast<const Trk::SubtractedVolumeBounds*> (volBounds); + const Trk::CombinedVolumeBounds* comb = dynamic_cast<const Trk::CombinedVolumeBounds*> (volBounds); + const Trk::SimplePolygonBrepVolumeBounds* spb = dynamic_cast<const Trk::SimplePolygonBrepVolumeBounds*> (volBounds); + const Trk::PrismVolumeBounds* prism = dynamic_cast<const Trk::PrismVolumeBounds*> (volBounds); + + if(box) ATH_MSG_VERBOSE(" findVolumeSpan box " ); + if(trd) ATH_MSG_VERBOSE(" findVolumeSpan trd " ); + if(dtrd) ATH_MSG_VERBOSE( " findVolumeSpan dtrd " ); + if(bcyl) ATH_MSG_VERBOSE(" findVolumeSpan bcyl " ); + if(cyl) ATH_MSG_VERBOSE(" findVolumeSpan cyl " ); + if(sub) ATH_MSG_VERBOSE(" findVolumeSpan sub " ); + if(comb) ATH_MSG_VERBOSE(" findVolumeSpan comb " ); + if(spb) ATH_MSG_VERBOSE(" findVolumeSpan spb " ); + if(prism) ATH_MSG_VERBOSE(" findVolumeSpan prism " ); + + if (sub) return findVolumeSpan(&(sub->outer()->volumeBounds()),transform*sub->outer()->transform(),zTol,phiTol,aLVC); + + if (comb) { + const Muon::Span* s1 = findVolumeSpan(&(comb->first()->volumeBounds()),transform*comb->first()->transform(),zTol,phiTol,aLVC); + const Muon::Span* s2 = findVolumeSpan(&(comb->second()->volumeBounds()),transform*comb->second()->transform(),zTol,phiTol,aLVC); + + ATH_MSG_VERBOSE( "Combined span1:"<<name()<< ","<<(*s1)[0]<<","<< (*s1)[1]<<","<<(*s1)[2]<<"," << (*s1)[3]<<","<< (*s1)[4]<<","<< (*s1)[5]); + ATH_MSG_VERBOSE( "Combined span2:"<<name()<< ","<<(*s2)[0]<<","<< (*s2)[1]<<","<<(*s2)[2]<<"," << (*s2)[3]<<","<< (*s2)[4]<<","<< (*s2)[5]); + + Muon::Span scomb; + scomb.reserve(6); + scomb.push_back(fmin((*s1)[0],(*s2)[0])); + scomb.push_back(fmax((*s1)[1],(*s2)[1])); + scomb.push_back(fmin((*s1)[2],(*s2)[2])); + scomb.push_back(fmax((*s1)[3],(*s2)[3])); + scomb.push_back(fmin((*s1)[4],(*s2)[4])); + scomb.push_back(fmax((*s1)[5],(*s2)[5])); + return new Muon::Span(scomb); + } + + // loop over edges ... + double minZ = aLVC.m_outerEndcapZ ; double maxZ = - aLVC.m_outerEndcapZ; + double minPhi = 2*M_PI; double maxPhi = 0.; + double minR = aLVC.m_outerBarrelRadius; double maxR = 0.; + std::vector<Amg::Vector3D> edges; + edges.reserve(16); + Muon::Span span; + span.reserve(6); + + double cylZcorr = 0.; + if (box) { + edges.push_back( Amg::Vector3D(box->halflengthX(),box->halflengthY(),box->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-box->halflengthX(),box->halflengthY(),box->halflengthZ()) ); + edges.push_back( Amg::Vector3D(box->halflengthX(),-box->halflengthY(),box->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-box->halflengthX(),-box->halflengthY(),box->halflengthZ()) ); + edges.push_back( Amg::Vector3D(box->halflengthX(),box->halflengthY(),-box->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-box->halflengthX(),box->halflengthY(),-box->halflengthZ()) ); + edges.push_back( Amg::Vector3D(box->halflengthX(),-box->halflengthY(),-box->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-box->halflengthX(),-box->halflengthY(),-box->halflengthZ()) ); + edges.push_back( Amg::Vector3D(0.,0.,-box->halflengthZ()) ); + edges.push_back( Amg::Vector3D(0.,0., box->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-box->halflengthX(),0.,0.) ); + edges.push_back( Amg::Vector3D( box->halflengthX(),0.,0.) ); + edges.push_back( Amg::Vector3D(0.,-box->halflengthY(),0.) ); + edges.push_back( Amg::Vector3D(0., box->halflengthY(),0.) ); + } + if (trd) { +// std::cout << " Trapezoid minHalflengthX " << trd->minHalflengthX() << " maxHalflengthX() " << trd->maxHalflengthX() << " halflengthY() " << trd->halflengthY() << " halflengthZ " << trd->halflengthZ() << std::endl; + + edges.push_back( Amg::Vector3D(trd->maxHalflengthX(),trd->halflengthY(),trd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-trd->maxHalflengthX(),trd->halflengthY(),trd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(trd->minHalflengthX(),-trd->halflengthY(),trd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-trd->minHalflengthX(),-trd->halflengthY(),trd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(trd->maxHalflengthX(),trd->halflengthY(),-trd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-trd->maxHalflengthX(),trd->halflengthY(),-trd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(trd->minHalflengthX(),-trd->halflengthY(),-trd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-trd->minHalflengthX(),-trd->halflengthY(),-trd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(0.,0.,-trd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(0.,0., trd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-0.5*(trd->minHalflengthX()-trd->maxHalflengthX()),0.,0.) ); + edges.push_back( Amg::Vector3D( 0.5*(trd->minHalflengthX()-trd->maxHalflengthX()),0.,0.) ); + edges.push_back( Amg::Vector3D(0.,-trd->halflengthY(),0.) ); + edges.push_back( Amg::Vector3D(0., trd->halflengthY(),0.) ); + } + if (dtrd) { + edges.push_back( Amg::Vector3D( dtrd->maxHalflengthX(),2*dtrd->halflengthY2(),dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-dtrd->maxHalflengthX(),2*dtrd->halflengthY2(),dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D( dtrd->medHalflengthX(),0.,dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-dtrd->medHalflengthX(),0.,dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D( dtrd->minHalflengthX(),-2*dtrd->halflengthY1(),dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-dtrd->minHalflengthX(),-2*dtrd->halflengthY1(),dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D( dtrd->maxHalflengthX(),2*dtrd->halflengthY2(),-dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-dtrd->maxHalflengthX(),2*dtrd->halflengthY2(),-dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D( dtrd->medHalflengthX(),0.,-dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-dtrd->medHalflengthX(),0.,-dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D( dtrd->minHalflengthX(),-2*dtrd->halflengthY1(),-dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(-dtrd->minHalflengthX(),-2*dtrd->halflengthY1(),-dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(0.,0.,-dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(0.,0., dtrd->halflengthZ()) ); + edges.push_back( Amg::Vector3D(0.,-2*dtrd->halflengthY1(),0.) ); + edges.push_back( Amg::Vector3D(0., 2*dtrd->halflengthY2(),0.) ); + } + if (bcyl) { + edges.push_back( Amg::Vector3D(0.,0.,bcyl->halflengthZ())); + edges.push_back( Amg::Vector3D(0.,0.,-bcyl->halflengthZ())); + } + if (cyl) { + edges.push_back( Amg::Vector3D(0.,0.,cyl->halflengthZ())); + edges.push_back( Amg::Vector3D(0.,0.,-cyl->halflengthZ())); + } + if (spb) { +#ifdef TRKDETDESCR_USEFLOATPRECISON +#define double float +#endif + const std::vector<std::pair<double, double> > vtcs = spb->xyVertices(); +#ifdef TRKDETDESCR_USEFLOATPRECISON +#undef double +#endif + for (unsigned int i=0;i<vtcs.size();i++) { + edges.push_back( Amg::Vector3D(vtcs[i].first,vtcs[i].second, spb->halflengthZ()) ); + edges.push_back( Amg::Vector3D(vtcs[i].first,vtcs[i].second, -spb->halflengthZ()) ); + } +// center + edges.push_back( Amg::Vector3D(0.,0.,spb->halflengthZ())); + edges.push_back( Amg::Vector3D(0.,0.,-spb->halflengthZ())); + + } + if (prism) { +#ifdef TRKDETDESCR_USEFLOATPRECISON +#define double float +#endif + const std::vector<std::pair<double, double> > vtcs = prism->xyVertices(); +#ifdef TRKDETDESCR_USEFLOATPRECISON +#undef double +#endif + for (unsigned int i=0;i<vtcs.size();i++) { + edges.push_back( Amg::Vector3D(vtcs[i].first,vtcs[i].second, prism->halflengthZ()) ); + edges.push_back( Amg::Vector3D(vtcs[i].first,vtcs[i].second, -prism->halflengthZ()) ); + } + edges.push_back( Amg::Vector3D(0.,0.,prism->halflengthZ())); + edges.push_back( Amg::Vector3D(0.,0.,-prism->halflengthZ())); + + } + // apply transform and get span + double minP0=M_PI; double maxP0 = 0.; double minP1=2*M_PI; double maxP1=M_PI; + // determine phiStep for prism and spb + double phiStep = 0.; + for (unsigned int ie=0; ie < edges.size() ; ie++) { + Amg::Vector3D gp = transform*edges[ie]; + double phi = gp.phi()+M_PI; + + ATH_MSG_VERBOSE( " local edges:"<< ie<<" x "<< edges[ie].x() << " y " << edges[ie].y() << " z " << edges[ie].z() << " phi "<< edges[ie].phi()); + ATH_MSG_VERBOSE( " Global edges:"<< ie<<" x "<< gp.x() << " y " << gp.y() << " z " << gp.z() << " phi position + pi "<< phi); + + if(ie>0&&phiStep<0.001) { + double phin = (transform*edges[ie-1]).phi() - M_PI; + double cph = cos(phi)*cos(phin) + sin(phi)*sin(phin); + phiStep = fabs(cph)<=1 ? acos(cph) : M_PI; // TODO check this logic + ATH_MSG_VERBOSE( " "<< ie<<" phiStep "<< phiStep ); + } + double rad = gp.perp(); + if (cyl || bcyl) { + double radius = 0.; double hz = 0.; + Amg::Vector3D dir = (transform*Amg::Vector3D(0.,0.,1.)); + double thAx = dir.theta(); + if (cyl) { radius = cyl->outerRadius(); hz = cyl->halflengthZ();} + if (bcyl) { radius = bcyl->outerRadius(); hz = bcyl->halflengthZ();} + if ( gp[2]-radius*sin(thAx) <minZ ) minZ = gp[2]-radius*sin(thAx); + if ( gp[2]+radius*sin(thAx) >maxZ ) maxZ = gp[2]+radius*sin(thAx); + if ( rad-radius*fabs(cos(thAx)) < minR ) minR = rad>radius ? rad-radius*fabs(cos(thAx)): 0; + if ( rad+radius*fabs(cos(thAx)) > maxR ) maxR = rad+radius*fabs(cos(thAx)); + // distance of cylinder axis and global axis + if (dir.perp()>0.001) { + // distance to minimal approach + double dMA = fabs(dir[0]*gp[0]+dir[1]*gp[1])/dir.perp()/dir.perp(); + double dMD = sqrt (fmax(0.,gp.perp()*gp.perp()-dMA*dMA)); + if (dMA<2*hz && dMD-radius < minR ) minR = fmax(0.,dMD-radius); + } + double dph = rad>0.001 ? atan(radius/rad) : M_PI; + if ( phi-dph <M_PI && phi-dph < minP0 ) minP0 = phi-dph; + if ( phi+dph <M_PI && phi+dph > maxP0 ) maxP0 = phi+dph; + if ( phi-dph >M_PI && phi-dph < minP1 ) minP1 = phi-dph; + if ( phi+dph >M_PI && phi+dph > maxP1 ) maxP1 = phi+dph; + } else { + if ( gp[2]<minZ ) minZ = gp[2]; + if ( gp[2]>maxZ ) maxZ = gp[2]; + if ( phi<M_PI && phi < minP0 ) minP0 = phi; + if ( phi<M_PI && phi > maxP0 ) maxP0 = phi; + if ( phi>M_PI && phi < minP1 ) minP1 = phi; + if ( phi>M_PI && phi > maxP1 ) maxP1 = phi; + //if ( phi < minPhi ) minPhi = phi; + //if ( phi > maxPhi ) maxPhi = phi; + if ( rad < minR ) minR = rad; + if ( rad > maxR ) maxR = rad; + } + } + if (maxPhi<minPhi) { + if (maxP0>=minP0 && maxP1<minP1) { minPhi = minP0; maxPhi = maxP0; } + else if ( maxP1>=minP1 && maxP0<minP0) { minPhi = minP1; maxPhi = maxP1; } + else if ( maxP1 - minP0 < (maxP0 - minP1+2*M_PI) ) { minPhi = minP0; maxPhi = maxP1; } + else { minPhi = minP1 ; maxPhi = maxP0; } + if (maxPhi<0.001 && minPhi>2*M_PI-0.001) {minPhi=0; maxPhi=2*M_PI;} + } +// +// correct edges for spb or prism +// + if(spb||prism) { + if(minP0<phiStep&&2*M_PI-maxP1<phiStep) { + minPhi = 0.; + maxPhi = 2*M_PI; + } + } + + if ( box || trd || dtrd || spb ) { + span.push_back( minZ - zTol ); + span.push_back( maxZ + zTol ); + span.push_back( minPhi - phiTol ); + span.push_back( maxPhi + phiTol ); + span.push_back( fmax(m_beamPipeRadius+0.001, minR - zTol) ); + span.push_back( maxR + zTol ); + } else if (bcyl || cyl ) { + span.push_back( minZ - cylZcorr -zTol ); + span.push_back( maxZ + cylZcorr +zTol ); + span.push_back( minPhi - phiTol ); + span.push_back( maxPhi + phiTol ); + span.push_back( fmax(m_beamPipeRadius+0.001, minR - zTol) ); + span.push_back( maxR + zTol ); + } else { + ATH_MSG_ERROR( name() <<" volume shape not recognized: "); + for (int i=0; i<6; i++) span.push_back(0.); + } + const Muon::Span* newSpan=new Muon::Span(span); + return newSpan; +} + +const std::vector<std::vector<std::pair<const Trk::DetachedTrackingVolume*,const Muon::Span*> >* >* Muon::MuonTrackingGeometryBuilderCond::findVolumesSpan(const std::vector<const Trk::DetachedTrackingVolume*>* objs, double zTol, double phiTol, LocalVariablesContainer &aLVC) const +{ + + if (!objs || !objs->size()) return 0; + std::vector<std::vector<std::pair<const Trk::DetachedTrackingVolume*,const Span*> >* >* spans = + new std::vector<std::vector<std::pair<const Trk::DetachedTrackingVolume*,const Span*> >* >(9); + // split MS into 9 blocks to speed up the build-up of geometry + for (unsigned int i=0;i<9;i++) (*spans)[i] = new std::vector<std::pair<const Trk::DetachedTrackingVolume*,const Span*> >; + for (unsigned int iobj=0; iobj<objs->size(); iobj++) { + Amg::Transform3D transform = (*objs)[iobj]->trackingVolume()->transform(); + const Muon::Span* span = findVolumeSpan(&((*objs)[iobj]->trackingVolume()->volumeBounds()), transform, zTol, phiTol, aLVC); + double x0 = (*objs)[iobj]->trackingVolume()->X0; + double intX0 = fabs((*span)[0]-(*span)[1])/(x0+0.000000001); + double l0 = (*objs)[iobj]->trackingVolume()->L0; + ATH_MSG_DEBUG( "span:"<<(*objs)[iobj]->name()<< ","<<(*span)[0]<<","<< (*span)[1]<<","<<(*span)[2]<<"," + << (*span)[3]<<","<< (*span)[4]<<","<< (*span)[5] << " X0 " << x0 << " L0 "<< l0 << " intX0 for span0 span1 " << intX0 ); + + int nspans = 0; + // negative outer wheel + if ( (*span)[0] < -m_bigWheel ) { + (*spans)[0]->push_back(std::pair<const Trk::DetachedTrackingVolume*,const Span*>((*objs)[iobj],span)); + nspans++; + } + // negative big wheel + if ( (*span)[0] < -aLVC.m_innerEndcapZ && (*span)[1]>-m_bigWheel ) { + (*spans)[1]->push_back(std::pair<const Trk::DetachedTrackingVolume*,const Span*>((*objs)[iobj],span)); + nspans++; + } + // neg.ect + if ( (*span)[0] < -m_ectZ && (*span)[1]>-aLVC.m_innerEndcapZ ) { + (*spans)[2]->push_back(std::pair<const Trk::DetachedTrackingVolume*,const Span*>((*objs)[iobj],span)); + nspans++; + } + // neg.small wheel + if ( (*span)[0] < -m_diskShieldZ && (*span)[1]>-m_ectZ ) { + (*spans)[3]->push_back(std::pair<const Trk::DetachedTrackingVolume*,const Span*>((*objs)[iobj],span)); + nspans++; + } + // barrel + if ( (*span)[0] < m_diskShieldZ && (*span)[1]> -m_diskShieldZ ) { +// && ((*span)[5]> m_innerBarrelRadius || (*span)[0]<-m_barrelZ || (*span)[1]>m_barrelZ) ) { + (*spans)[4]->push_back(std::pair<const Trk::DetachedTrackingVolume*,const Span*>((*objs)[iobj],span)); + nspans++; + } + // pos.small wheel + if ( (*span)[0] < m_ectZ && (*span)[1]> m_diskShieldZ ) { + (*spans)[5]->push_back(std::pair<const Trk::DetachedTrackingVolume*,const Span*>((*objs)[iobj],span)); + nspans++; + } + // pos.ect + if ( (*span)[0] < aLVC.m_innerEndcapZ && (*span)[1]> m_ectZ ) { + (*spans)[6]->push_back(std::pair<const Trk::DetachedTrackingVolume*,const Span*>((*objs)[iobj],span)); + nspans++; + } + // positive big wheel + if ( (*span)[0] < m_bigWheel && (*span)[1]> aLVC.m_innerEndcapZ ) { + (*spans)[7]->push_back(std::pair<const Trk::DetachedTrackingVolume*,const Span*>((*objs)[iobj],span)); + nspans++; + } + // positive outer wheel + if ( (*span)[1] > m_bigWheel ) { + (*spans)[8]->push_back(std::pair<const Trk::DetachedTrackingVolume*,const Span*>((*objs)[iobj],span)); + nspans++; + } + + if(nspans == 0) ATH_MSG_WARNING( " object not selected in span regions " << (*objs)[iobj]->name() ); + if(nspans > 1) ATH_MSG_VERBOSE( " object selected in " << nspans << " span regions " << (*objs)[iobj]->name() ); + + aLVC.m_spans.push_back(span); // keep track of things to delete + } + + return spans; +} + + +const Trk::TrackingVolume* Muon::MuonTrackingGeometryBuilderCond::processVolume(const Trk::Volume* vol, int etaN , int phiN, std::string volumeName, LocalVariablesContainer& aLVC) const +{ + + const Trk::TrackingVolume* tVol = 0; + + unsigned int colorCode = m_colorCode; + + std::vector<const Trk::DetachedTrackingVolume*> blendVols; + + // partitions ? include protection against wrong setup + if (etaN < 1 || phiN < 1) { + ATH_MSG_ERROR( name() << "wrong partition setup" ); + etaN = 1; + phiN = 1; + } + if ( etaN * phiN > 1 ) { // partition + const Trk::CylinderVolumeBounds* cyl=dynamic_cast<const Trk::CylinderVolumeBounds*> (&(vol->volumeBounds())); + if (!cyl) { + ATH_MSG_ERROR( " process volume: volume cylinder boundaries not retrieved, return 0 " ); + return 0; + } + // subvolume boundaries + Trk::CylinderVolumeBounds* subBds = 0; + + double phiSect = M_PI/phiN; + double etaSect = (cyl->halflengthZ())/etaN; + + subBds = new Trk::CylinderVolumeBounds(cyl->innerRadius(), cyl->outerRadius(), phiSect,etaSect); + const Trk::Volume* protVol= new Trk::Volume(0, subBds); + + // create subvolumes & BinnedArray + std::vector<Trk::TrackingVolumeOrderPosition> subVolumes; + std::vector<const Trk::TrackingVolume*> sVols; // for gluing + std::vector<const Trk::TrackingVolume*> sVolsNeg; // for gluing + std::vector<const Trk::TrackingVolume*> sVolsPos; // for gluing + for (int eta = 0; eta < etaN; eta++) { + if (colorCode>0) colorCode = 26 - colorCode; + // reference point for the check of envelope + double posZ = (vol->center())[2]+ etaSect * (2.*eta+1.-etaN) ; + double posR = 0.5*(cyl->innerRadius()+cyl->outerRadius()); + int geoSignature = 4; + // loop over inner cutouts + for (unsigned int in=1; in<aLVC.m_msCutoutsIn.size(); in++) { + if (posZ>=aLVC.m_msCutoutsIn[in].second && posZ<=aLVC.m_msCutoutsIn[in-1].second) { + if (posR < aLVC.m_msCutoutsIn[in].first) geoSignature=2; + break; + } + } + if (geoSignature == 4) { + // loop over outer cutouts + for (unsigned int io=1; io<aLVC.m_msCutoutsOut.size(); io++) { + if (posZ>=aLVC.m_msCutoutsOut[io-1].second && posZ<=aLVC.m_msCutoutsOut[io].second) { + if (posR > aLVC.m_msCutoutsOut[io].first) geoSignature=5; + break; + } + } + } + for (int phi = 0; phi < phiN; phi++) { + if (colorCode>0) colorCode = 26 - colorCode; + // define subvolume + Amg::Transform3D transf(Amg::AngleAxis3D(phiSect*(2*phi+1), Amg::Vector3D(0.,0.,1.))*Amg::Translation3D(Amg::Vector3D(0.,0.,posZ))); + const Trk::Volume* subVol= new Trk::Volume(*protVol, transf); + // enclosed muon objects ? + std::string volName = volumeName +MuonGM::buildString(eta,2) +MuonGM::buildString(phi,2) ; + blendVols.clear(); + std::vector<const Trk::DetachedTrackingVolume*>* detVols= getDetachedObjects( subVol, blendVols,aLVC); + const Trk::TrackingVolume* sVol = new Trk::TrackingVolume( *subVol, + aLVC.m_muonMaterial, + detVols, + volName ); + // statistics + m_frameNum++ ; if (detVols) m_frameStat += detVols->size(); + // prepare blending + if (m_blendInertMaterial && blendVols.size()) { + for (unsigned int id=0;id<blendVols.size();id++) { + if (!aLVC.m_blendMap[blendVols[id]]) { + aLVC.m_blendMap[blendVols[id]] = new std::vector<const Trk::TrackingVolume*>; + aLVC.m_blendVols.push_back(blendVols[id]); + } + aLVC.m_blendMap[blendVols[id]]->push_back(sVol); + } + } + // + if (geoSignature == 2) sVol->sign(Trk::BeamPipe); + if (geoSignature == 5) sVol->sign(Trk::Cavern); + sVol->registerColorCode(colorCode); + // reference position + Amg::Vector3D gp(subBds->outerRadius(),0.,0.); + //subVolumes.push_back(Trk::TrackingVolumeOrderPosition(Trk::SharedObject<const Trk::TrackingVolume>(sVol, true), + // Amg::Vector3D(transf*gp))); + /* The above was passing a SharedObject with the ndel == True + * now that SharedObject is a typeded to std::shared_ptr , pass a no-op deleter + */ + subVolumes.push_back(Trk::TrackingVolumeOrderPosition(Trk::SharedObject<const Trk::TrackingVolume>(sVol, Trk::do_not_delete<const Trk::TrackingVolume>), + Amg::Vector3D(transf*gp))); + //glue subVolumes + sVols.push_back(sVol); + if (eta==0) sVolsNeg.push_back(sVol); + if (eta==etaN-1) sVolsPos.push_back(sVol); + // in phi + if ( phiN>1 && phi>0) { + m_trackingVolumeHelper->glueTrackingVolumes(*sVol, Trk::tubeSectorNegativePhi, + *(sVols[eta*phiN+phi-1]), Trk::tubeSectorPositivePhi); + if ( phi==phiN-1 ) m_trackingVolumeHelper->glueTrackingVolumes(*(sVols[eta*phiN]), Trk::tubeSectorNegativePhi, + *sVol, Trk::tubeSectorPositivePhi); + } + // in eta + if ( etaN>1 && eta>0) m_trackingVolumeHelper->glueTrackingVolumes(*sVol, Trk::negativeFaceXY, + *(sVols[(eta-1)*phiN+phi]), Trk::positiveFaceXY); + // + delete subVol; //shouldn't need this any more + } + } + + //Trk::BinUtility2DPhiZ* volBinUtil=new Trk::BinUtility2DPhiZ(phiN,etaN,subBds->outerRadius(),cyl->halflengthZ(),M_PI, new Amg::Transform3D(vol->transform())); + Trk::BinUtility buPhi( phiN, -M_PI, M_PI, Trk::closed, Trk::binPhi ); + const Trk::BinUtility buZ( etaN, vol->transform().translation()[2]-cyl->halflengthZ(), + vol->transform().translation()[2]+cyl->halflengthZ(), Trk::open, Trk::binZ ); + buPhi += buZ; + + Trk::BinUtility* volBinUtil=new Trk::BinUtility(buPhi); // TODO verify ordering PhiZ vs. ZPhi + + delete protVol; + Trk::BinnedArray2D<Trk::TrackingVolume>* subVols=new Trk::BinnedArray2D<Trk::TrackingVolume>(subVolumes,volBinUtil); + + tVol = new Trk::TrackingVolume( *vol, + aLVC.m_muonMaterial, + 0,subVols, + volumeName); + // register glue volumes + const Trk::GlueVolumesDescriptor& volGlueVolumes = tVol->glueVolumesDescriptor(); + volGlueVolumes.registerGlueVolumes(Trk::tubeInnerCover,sVols); + volGlueVolumes.registerGlueVolumes(Trk::tubeOuterCover,sVols); + volGlueVolumes.registerGlueVolumes(Trk::negativeFaceXY,sVolsNeg); + volGlueVolumes.registerGlueVolumes(Trk::positiveFaceXY,sVolsPos); + + } else { + // enclosed muon objects ? + blendVols.clear(); + std::vector<const Trk::DetachedTrackingVolume*>* muonObjs = getDetachedObjects( vol, blendVols,aLVC); + + tVol = new Trk::TrackingVolume( *vol, + aLVC.m_muonMaterial, + muonObjs, + volumeName); + // statistics + m_frameNum++ ; if (muonObjs) m_frameStat += muonObjs->size(); + // prepare blending + if (m_blendInertMaterial && blendVols.size()) { + for (unsigned int id=0;id<blendVols.size();id++) { + if (!aLVC.m_blendMap[blendVols[id]]) { + aLVC.m_blendMap[blendVols[id]] = new std::vector<const Trk::TrackingVolume*>; + aLVC.m_blendVols.push_back(blendVols[id]); + } + aLVC.m_blendMap[blendVols[id]]->push_back(tVol); + } + } + } + + return tVol; +} + +const Trk::TrackingVolume* Muon::MuonTrackingGeometryBuilderCond::processVolume(const Trk::Volume* vol, int mode , std::string volumeName, LocalVariablesContainer& aLVC) const +{ + ATH_MSG_VERBOSE( name() << "processing volume in mode:"<< mode ); + + // mode : -1 ( adjusted z/phi partition ) + // 0 ( -"- plus barrel H binning ) + // 0 ( -"- plus inner endcap H binning ) + // 0 ( -"- plus outer endcap H binning ) + + const Trk::TrackingVolume* tVol = 0; + + unsigned int colorCode = m_colorCode; + + std::vector<const Trk::DetachedTrackingVolume* > blendVols; + + //getPartitionFromMaterial(vol); + + // retrieve cylinder + const Trk::CylinderVolumeBounds* cyl=dynamic_cast<const Trk::CylinderVolumeBounds*> (&(vol->volumeBounds())); + if (!cyl) { + ATH_MSG_ERROR( " process volume: volume cylinder boundaries not retrieved, return 0 " ); + return 0; + } + // create vector of zSteps for this volume + std::vector<float> zSteps; + std::vector<int> zTypes; + zSteps.clear(); zTypes.clear(); + double zPos = vol->center()[2]; + double hz = cyl->halflengthZ(); + double z1 = zPos-hz; double z2 = zPos+hz ; + zSteps.push_back(z1); + for (unsigned int iz=0;iz<aLVC.m_zPartitions.size();iz++) { + if ( aLVC.m_zPartitions[iz]==zSteps.front()) zTypes.push_back(aLVC.m_zPartitionsType[iz]); + if ( aLVC.m_zPartitions[iz]> z1 && aLVC.m_zPartitions[iz] < z2 ) { + zSteps.push_back(aLVC.m_zPartitions[iz]); + if (!zTypes.size()) { + if (iz==0) zTypes.push_back(0); + else zTypes.push_back(aLVC.m_zPartitionsType[iz-1]); + } + zTypes.push_back(aLVC.m_zPartitionsType[iz]); + z1 = aLVC.m_zPartitions[iz]; + } + } + zSteps.push_back(z2); + + for (unsigned int iz=0;iz<zSteps.size(); iz++) ATH_MSG_DEBUG( "z partition in volume:"<<volumeName<<":"<<iz<<":"<<zSteps[iz]); + + // phi binning + if (fabs(zPos)> m_barrelZ && cyl->outerRadius()<aLVC.m_outerBarrelRadius) getPhiParts(0,aLVC); + else if (fabs(zPos)<= m_ectZ) getPhiParts(2,aLVC); + else if (fabs(zPos)<= aLVC.m_innerEndcapZ) getPhiParts(3,aLVC); + else if (fabs(zPos)> m_outerWheel && cyl->outerRadius()> m_outerShieldRadius ) getPhiParts(1,aLVC); + else if (fabs(zPos)> aLVC.m_innerEndcapZ && fabs(zPos)<m_bigWheel && cyl->outerRadius()> m_outerShieldRadius ) getPhiParts(1,aLVC); + else getPhiParts(0,aLVC); + + // R/H binning ? + unsigned int etaN = zSteps.size()-1; + unsigned int phiN = aLVC.m_adjustedPhi.size(); + + int phiTypeMax = 0; // count different partitions + + if ( mode > -1 ) { + // create z,phi bin utilities + //Trk::BinUtility1DZZ* zBinUtil = new Trk::BinUtility1DZZ(zSteps); + //Trk::BinUtility1DF* pBinUtil = new Trk::BinUtility1DF(m_adjustedPhi); + Trk::BinUtility* zBinUtil = new Trk::BinUtility(zSteps, Trk::open, Trk::binZ ); + Trk::BinUtility* pBinUtil = new Trk::BinUtility(aLVC.m_adjustedPhi, Trk::closed, Trk::binPhi ); + std::vector<std::vector<Trk::BinUtility*> >* hBinUtil=new std::vector<std::vector<Trk::BinUtility*> >; + for (unsigned iz=0;iz < zSteps.size()-1; iz++) { + std::vector<Trk::BinUtility*> phBinUtil; + for (unsigned ip=0;ip < aLVC.m_adjustedPhi.size(); ip++) { + // retrieve reference phi + float phiRef = 0.5*aLVC.m_adjustedPhi[ip]; + if (ip<aLVC.m_adjustedPhi.size()-1) phiRef += 0.5*aLVC.m_adjustedPhi[ip+1] ; + else phiRef += 0.5*aLVC.m_adjustedPhi[0]+M_PI ; + + if (aLVC.m_adjustedPhiType[ip]>phiTypeMax) phiTypeMax = aLVC.m_adjustedPhiType[ip]; + for (std::pair<int,float> i: aLVC.m_hPartitions[mode][zTypes[iz]][aLVC.m_adjustedPhiType[ip]]) { + ATH_MSG_VERBOSE( " mode " << mode << " phiRef " << phiRef << " zTypes[iz] " << zTypes[iz] << " m_adjustedPhiType[ip] " << aLVC.m_adjustedPhiType[ip] << " hPartitions " << i.second ); + } + phBinUtil.push_back(new Trk::BinUtility(phiRef,aLVC.m_hPartitions[mode][zTypes[iz]][aLVC.m_adjustedPhiType[ip]])); + } + hBinUtil->push_back(phBinUtil); + } + + // create subvolumes & BinnedArray + std::vector<Trk::TrackingVolumeOrderPosition> subVolumesVect; + std::vector<std::vector<std::vector<const Trk::TrackingVolume*> > > subVolumes; + std::vector<std::vector<Trk::SharedObject<Trk::BinnedArray<Trk::TrackingVolume> > > > hBins; + std::vector<const Trk::TrackingVolume*> sVolsInn; // for gluing + std::vector<const Trk::TrackingVolume*> sVolsOut; // for gluing + std::vector<const Trk::TrackingVolume*> sVolsNeg; // for gluing + std::vector<const Trk::TrackingVolume*> sVolsPos; // for gluing + for (unsigned int eta = 0; eta < zSteps.size()-1; eta++) { + if (colorCode>0) colorCode = 6 -colorCode; + double posZ = 0.5*(zSteps[eta] + zSteps[eta+1]) ; + double hZ = 0.5*fabs(zSteps[eta+1] - zSteps[eta]) ; + std::vector<std::vector<const Trk::TrackingVolume*> > phiSubs; + std::vector<Trk::SharedObject<Trk::BinnedArray<Trk::TrackingVolume> > > phBins; + std::vector<int> phiType(phiTypeMax+1,-1); // indication of first phi/R partition built for a given type (for cloning) + std::vector<std::vector<Trk::Volume*> > garbVol(phiTypeMax+1); + unsigned int pCode = 1; + for (unsigned int phi = 0; phi < phiN; phi++) { + pCode = (colorCode>0) ? 3-pCode : 0; + double posPhi = 0.5*aLVC.m_adjustedPhi[phi]; + double phiSect = 0.; + if (phi<phiN-1) { + posPhi += 0.5*aLVC.m_adjustedPhi[phi+1] ; + phiSect = 0.5*fabs(aLVC.m_adjustedPhi[phi+1]-aLVC.m_adjustedPhi[phi]); + } else { + posPhi += 0.5*aLVC.m_adjustedPhi[0]+M_PI ; + phiSect = 0.5*fabs(aLVC.m_adjustedPhi[0]+2*M_PI-aLVC.m_adjustedPhi[phi]); + } + std::vector<std::pair<int,float> > hSteps = aLVC.m_hPartitions[mode][zTypes[eta]][aLVC.m_adjustedPhiType[phi]]; + std::vector<const Trk::TrackingVolume*> hSubs; + std::vector<Trk::TrackingVolumeOrderPosition> hSubsTr; + int phiP = phiType[aLVC.m_adjustedPhiType[phi]]; + + unsigned int hCode = 1; + for (unsigned int h = 0; h < hSteps.size()-1; h++) { + hCode = colorCode>0 ? 1 - hCode : 0; + // similar volume may exist already + Trk::Volume* subVol=0; + Amg::Transform3D* transf = new Amg::Transform3D(Amg::AngleAxis3D(posPhi,Amg::Vector3D(0.,0.,1.))*Amg::Translation3D(Amg::Vector3D(0.,0.,posZ))); + // + int volType = 0; // cylinder + if ( hSteps[h].first == 1 && hSteps[h+1].first == 0 ) volType = 1; + if ( hSteps[h].first == 0 && hSteps[h+1].first == 1 ) volType = 2; + if ( hSteps[h].first == 1 && hSteps[h+1].first == 1 ) volType = 3; + // define subvolume + if (phiP>-1 ) { + subVol = new Trk::Volume(*(phiSubs[phiP][h]),(*transf)*phiSubs[phiP][h]->transform().inverse()); + } else if ( phiSect<0.5*M_PI) { + Trk::BevelledCylinderVolumeBounds* subBds = new Trk::BevelledCylinderVolumeBounds(hSteps[h].second, + hSteps[h+1].second, + phiSect, + hZ, + volType); + subVol = new Trk::Volume(transf, subBds); + } else { + Trk::CylinderVolumeBounds* subBds = new Trk::CylinderVolumeBounds(hSteps[h].second, + hSteps[h+1].second, + phiSect, + hZ); + subVol = new Trk::Volume(transf, subBds); + } + + // enclosed muon objects ? also adjusts material properties in case of material blend + std::string volName = volumeName +MuonGM::buildString(eta,2) +MuonGM::buildString(phi,2) +MuonGM::buildString(h,2) ; + blendVols.clear(); + std::vector<const Trk::DetachedTrackingVolume*>* detVols= getDetachedObjects( subVol, blendVols,aLVC); + + const Trk::TrackingVolume* sVol = new Trk::TrackingVolume( *subVol, + aLVC.m_muonMaterial, + detVols, + volName ); + + // statistics + m_frameNum++ ; if (detVols) m_frameStat += detVols->size(); + // prepare blending + if (m_blendInertMaterial && blendVols.size()) { + for (unsigned int id=0;id<blendVols.size();id++) { + if (!aLVC.m_blendMap[blendVols[id]]) { + aLVC.m_blendMap[blendVols[id]] = new std::vector<const Trk::TrackingVolume*>; + aLVC.m_blendVols.push_back(blendVols[id]); + } + aLVC.m_blendMap[blendVols[id]]->push_back(sVol); + } + } + // reference point for the check of envelope + double posR = 0.5*(hSteps[h].second+hSteps[h+1].second); + // loop over inner cutouts + for (unsigned int in=1; in<aLVC.m_msCutoutsIn.size(); in++) { + if (posZ>=aLVC.m_msCutoutsIn[in].second && posZ<=aLVC.m_msCutoutsIn[in-1].second) { + if (posR < aLVC.m_msCutoutsIn[in].first) sVol->sign(Trk::BeamPipe); + break; + } + } + // loop over outer cutouts + for (unsigned int io=1; io<aLVC.m_msCutoutsOut.size(); io++) { + if (posZ>=aLVC.m_msCutoutsOut[io-1].second && posZ<=aLVC.m_msCutoutsOut[io].second) { + if (posR > aLVC.m_msCutoutsOut[io].first) sVol->sign(Trk::Cavern); + break; + } + } + // + sVol->registerColorCode(colorCode+pCode+hCode); + // reference position + Amg::Vector3D gp(0.5*(hSteps[h].second+hSteps[h+1].second),0.,0.); + subVolumesVect.push_back(Trk::TrackingVolumeOrderPosition(Trk::SharedObject<const Trk::TrackingVolume>(sVol), + Amg::Vector3D((*transf)*gp))); + hSubsTr.push_back(Trk::TrackingVolumeOrderPosition(Trk::SharedObject<const Trk::TrackingVolume>(sVol, Trk::do_not_delete<const Trk::TrackingVolume>), + Amg::Vector3D((*transf)*gp))); + hSubs.push_back(sVol); + + // cleanup + if (phiP>-1) {delete transf; delete subVol;} + else garbVol[aLVC.m_adjustedPhiType[phi]].push_back(subVol); // don't delete before cloned + + //glue subVolume + if (h==0) sVolsInn.push_back(sVol); + if (h==hSteps.size()-2) sVolsOut.push_back(sVol); + if (eta==0) sVolsNeg.push_back(sVol); + if (eta==etaN-1) sVolsPos.push_back(sVol); + // in R/H + if (h>0) { // glue 'manually' + if (volType == 1 || volType == 3 ) { // plane surface + m_trackingVolumeHelper->setOutsideTrackingVolume(*sVol, Trk::tubeSectorInnerCover,hSubs[h-1]); + m_trackingVolumeHelper->setOutsideTrackingVolume(*(hSubs[h-1]), Trk::tubeSectorOuterCover,sVol); + } else { // cylinder surface + m_trackingVolumeHelper->setInsideTrackingVolume(*sVol, Trk::tubeSectorInnerCover,hSubs[h-1]); + m_trackingVolumeHelper->setOutsideTrackingVolume(*(hSubs[h-1]), Trk::tubeSectorOuterCover,sVol); + } + } + // in phi + if ( phiN>1 && phi>0) { + m_trackingVolumeHelper->setOutsideTrackingVolumeArray(*sVol, Trk::tubeSectorNegativePhi,phBins[phi-1]); + if ( phi==phiN-1 ) m_trackingVolumeHelper->setOutsideTrackingVolumeArray(*sVol, Trk::tubeSectorPositivePhi, phBins[0]); + } + // in eta + if ( etaN>1 && eta>0) m_trackingVolumeHelper->setOutsideTrackingVolumeArray(*sVol, Trk::negativeFaceXY, hBins[eta-1][phi]); + // + } + phiSubs.push_back(hSubs); + Trk::BinnedArray1D<Trk::TrackingVolume>* volBinArray = new Trk::BinnedArray1D<Trk::TrackingVolume>(hSubsTr,(*hBinUtil)[eta][phi]->clone()); + phBins.push_back(Trk::SharedObject<Trk::BinnedArray<Trk::TrackingVolume> >(volBinArray)); + // save link to current partition for cloning + if (phiP<0) phiType[aLVC.m_adjustedPhiType[phi]] = phi; + + // finish phi gluing + if (phiN>1 && phi>0) { + for (unsigned int j=0; j<phiSubs[phi-1].size(); j++) { + m_trackingVolumeHelper->setOutsideTrackingVolumeArray(*(phiSubs[phi-1][j]), Trk::tubeSectorPositivePhi,phBins[phi]); + } + } + if (phiN>1 && phi==phiN-1) { + for (unsigned int j=0; j<phiSubs[0].size(); j++) { + m_trackingVolumeHelper->setOutsideTrackingVolumeArray(*(phiSubs[0][j]), Trk::tubeSectorNegativePhi,phBins[phi]); + } + } + // finish eta gluing + if ( etaN>1 && eta>0) { + for (unsigned int j=0; j<subVolumes[eta-1][phi].size(); j++) { + m_trackingVolumeHelper->setOutsideTrackingVolumeArray(*(subVolumes[eta-1][phi][j]), Trk::positiveFaceXY,phBins[phi]); + } + } + } + subVolumes.push_back(phiSubs); + hBins.push_back(phBins); + // get rid of the garbage + for (unsigned int j=0;j<garbVol.size();j++) + for (unsigned int jj=0;jj<garbVol[j].size();jj++) delete garbVol[j][jj]; + } + + //Trk::BinUtility3DZFH* volBinUtil=new Trk::BinUtility3DZFH(zBinUtil,pBinUtil,hBinUtil,new Amg::Transform3D(vol->transform())); + + Trk::BinnedArray1D1D1D<Trk::TrackingVolume>* subVols=new Trk::BinnedArray1D1D1D<Trk::TrackingVolume>(subVolumesVect,zBinUtil,pBinUtil,hBinUtil); + + tVol = new Trk::TrackingVolume( *vol, + aLVC.m_muonMaterial, + 0,subVols, + volumeName); + // register glue volumes + const Trk::GlueVolumesDescriptor& volGlueVolumes = tVol->glueVolumesDescriptor(); + volGlueVolumes.registerGlueVolumes(Trk::tubeInnerCover,sVolsInn); + volGlueVolumes.registerGlueVolumes(Trk::tubeOuterCover,sVolsOut); + volGlueVolumes.registerGlueVolumes(Trk::negativeFaceXY,sVolsNeg); + volGlueVolumes.registerGlueVolumes(Trk::positiveFaceXY,sVolsPos); + + return tVol; + } + + // proceed with 2D z/phi binning + // partitions ? include protection against wrong setup + if (phiN < 1) { + ATH_MSG_ERROR( name() << "wrong partition setup" ); + phiN = 1; + } else { + ATH_MSG_VERBOSE( name() << "partition setup:(z,phi):"<<etaN<<","<<phiN ); + } + + if ( etaN * phiN > 1 ) { // partition + // subvolume boundaries + Trk::CylinderVolumeBounds* subBds=0; + + // create subvolumes & BinnedArray + std::vector<Trk::TrackingVolumeOrderPosition> subVolumes(etaN*phiN); + std::vector<const Trk::TrackingVolume*> sVols(etaN*phiN); // for gluing + std::vector<const Trk::TrackingVolume*> sVolsNeg(phiN); // for gluing + std::vector<const Trk::TrackingVolume*> sVolsPos(phiN); // for gluing + for (unsigned int eta = 0; eta < zSteps.size()-1; eta++) { + double posZ = 0.5*(zSteps[eta] + zSteps[eta+1]) ; + double hZ = 0.5*fabs(zSteps[eta+1] - zSteps[eta]) ; + colorCode = 26 -colorCode; + for (unsigned int phi = 0; phi < phiN; phi++) { + colorCode = 26 -colorCode; + double posPhi = 0.5*aLVC.m_adjustedPhi[phi]; + double phiSect = 0.; + if (phi<phiN-1) { + posPhi += 0.5*aLVC.m_adjustedPhi[phi+1] ; + phiSect = 0.5*fabs(aLVC.m_adjustedPhi[phi+1]-aLVC.m_adjustedPhi[phi]); + } else { + posPhi += 0.5*aLVC.m_adjustedPhi[0]+M_PI ; + phiSect = 0.5*fabs(aLVC.m_adjustedPhi[0]+2*M_PI-aLVC.m_adjustedPhi[phi]); + } + // define subvolume + subBds = new Trk::CylinderVolumeBounds(cyl->innerRadius(), + cyl->outerRadius(), + phiSect, + hZ); + Amg::Transform3D* transf = new Amg::Transform3D(Amg::AngleAxis3D(posPhi,Amg::Vector3D(0.,0.,1.))*Amg::Translation3D(Amg::Vector3D(0.,0.,posZ))); + Trk::Volume subVol(transf, subBds); + // enclosed muon objects ? + std::string volName = volumeName +MuonGM::buildString(eta,2) +MuonGM::buildString(phi,2) ; + + Trk::Material mat=aLVC.m_muonMaterial; + blendVols.clear(); + std::vector<const Trk::DetachedTrackingVolume*>* detVols= getDetachedObjects( &subVol, blendVols,aLVC); + const Trk::TrackingVolume* sVol = new Trk::TrackingVolume( subVol, + aLVC.m_muonMaterial, + detVols, + volName ); + // statistics + m_frameNum++ ; if (detVols) m_frameStat += detVols->size(); + // prepare blending + if (m_blendInertMaterial && blendVols.size()) { + for (unsigned int id=0;id<blendVols.size();id++) { + if (!aLVC.m_blendMap[blendVols[id]]) { + aLVC.m_blendMap[blendVols[id]] = new std::vector<const Trk::TrackingVolume*>; + aLVC.m_blendVols.push_back(blendVols[id]); + } + aLVC.m_blendMap[blendVols[id]]->push_back(sVol); + } + } + // reference point for the check of envelope + double posR = 0.5*(cyl->innerRadius()+cyl->outerRadius()); + // loop over inner cutouts + for (unsigned int in=1; in<aLVC.m_msCutoutsIn.size(); in++) { + if (posZ>=aLVC.m_msCutoutsIn[in].second && posZ<=aLVC.m_msCutoutsIn[in-1].second) { + if (posR < aLVC.m_msCutoutsIn[in].first) sVol->sign(Trk::BeamPipe); + break; + } + } + // loop over outer cutouts + for (unsigned int io=1; io<aLVC.m_msCutoutsOut.size(); io++) { + if (posZ>=aLVC.m_msCutoutsOut[io-1].second && posZ<=aLVC.m_msCutoutsOut[io].second) { + if (posR > aLVC.m_msCutoutsOut[io].first) sVol->sign(Trk::Cavern); + break; + } + } + //delete subVol; + sVol->registerColorCode(colorCode); + // reference position + Amg::Vector3D gp(subBds->outerRadius(),0.,0.); + //subVolumes.push_back(Trk::TrackingVolumeOrderPosition(Trk::SharedObject<const Trk::TrackingVolume>(sVol, true), + // Amg::Vector3D((*transf)*gp))); + subVolumes[phi*etaN+eta] = Trk::TrackingVolumeOrderPosition(Trk::SharedObject<const Trk::TrackingVolume>(sVol), + Amg::Vector3D((*transf)*gp)); + //glue subVolumes + //sVols[phi*etaN+eta] = sVol; + sVols[phiN*eta+phi] = sVol; + if (eta==0) sVolsNeg[phi]=sVol; + if (eta==etaN-1) sVolsPos[phi]=sVol; + // in phi + if ( phiN>1 && phi>0) { + m_trackingVolumeHelper->glueTrackingVolumes(*sVol, Trk::tubeSectorNegativePhi, + *(sVols[eta*phiN+phi-1]), Trk::tubeSectorPositivePhi); + if ( phi==phiN-1 ) m_trackingVolumeHelper->glueTrackingVolumes(*(sVols[eta*phiN]), Trk::tubeSectorNegativePhi, + *sVol, Trk::tubeSectorPositivePhi); + } + // in eta + if ( etaN>1 && eta>0) m_trackingVolumeHelper->glueTrackingVolumes(*sVol, Trk::negativeFaceXY, + *(sVols[(eta-1)*phiN+phi]), Trk::positiveFaceXY); + // + } + } + + //Trk::BinUtility2DZF* volBinUtil=new Trk::BinUtility2DZF(zSteps,m_adjustedPhi,new Amg::Transform3D(vol->transform())); + Trk::BinUtility zBinUtil(zSteps, Trk::BinningOption::open, Trk::BinningValue::binZ ); + const Trk::BinUtility pBinUtil(aLVC.m_adjustedPhi, Trk::BinningOption::closed, Trk::BinningValue::binPhi ); + + zBinUtil += pBinUtil; + + Trk::BinUtility* volBinUtil=new Trk::BinUtility(zBinUtil); // TODO verify ordering PhiZ vs. ZPhi + + Trk::BinnedArray2D<Trk::TrackingVolume>* subVols=new Trk::BinnedArray2D<Trk::TrackingVolume>(subVolumes,volBinUtil); + + tVol = new Trk::TrackingVolume( *vol, + aLVC.m_muonMaterial, + 0,subVols, + volumeName); + // register glue volumes + const Trk::GlueVolumesDescriptor& volGlueVolumes = tVol->glueVolumesDescriptor(); + volGlueVolumes.registerGlueVolumes(Trk::tubeInnerCover,sVols); + volGlueVolumes.registerGlueVolumes(Trk::tubeOuterCover,sVols); + volGlueVolumes.registerGlueVolumes(Trk::negativeFaceXY,sVolsNeg); + volGlueVolumes.registerGlueVolumes(Trk::positiveFaceXY,sVolsPos); + + } else { + // enclosed muon objects ? + blendVols.clear(); + std::vector<const Trk::DetachedTrackingVolume*>* muonObjs = getDetachedObjects( vol, blendVols,aLVC); + + tVol = new Trk::TrackingVolume( *vol, + aLVC.m_muonMaterial, + muonObjs, + volumeName); + // statistics + m_frameNum++ ; if (muonObjs) m_frameStat += muonObjs->size(); + // prepare blending + if (m_blendInertMaterial && blendVols.size()) { + for (unsigned int id=0;id<blendVols.size();id++) { + if (!aLVC.m_blendMap[blendVols[id]]) { + aLVC.m_blendMap[blendVols[id]] = new std::vector<const Trk::TrackingVolume*>; + aLVC.m_blendVols.push_back(blendVols[id]); + } + aLVC.m_blendMap[blendVols[id]]->push_back(tVol); + } + } + } + + return tVol; +} + +const Trk::TrackingVolume* Muon::MuonTrackingGeometryBuilderCond::processShield(const Trk::Volume* vol, int type,std::string volumeName, LocalVariablesContainer &aLVC) const +{ + ATH_MSG_VERBOSE( name() << "processing shield volume "<< volumeName<<" in mode:"<< type ); + + const Trk::TrackingVolume* tVol = 0; + + unsigned int colorCode = m_colorCode; + + std::vector<const Trk::DetachedTrackingVolume*> blendVols; + + //getPartitionFromMaterial(vol); + + // retrieve cylinder + const Trk::CylinderVolumeBounds* cyl=dynamic_cast<const Trk::CylinderVolumeBounds*> (&(vol->volumeBounds())); + if (!cyl) { + ATH_MSG_ERROR( " process volume: volume cylinder boundaries not retrieved, return 0 " ); + return 0; + } + // create vector of zSteps for this volume + std::vector<float> zSteps; + zSteps.clear(); + double zPos = vol->center()[2]; + double hz = cyl->halflengthZ(); + double z1 = zPos-hz; double z2 = zPos+hz ; + zSteps.push_back(z1); + for (unsigned int iz=0;iz<aLVC.m_shieldZPart.size();iz++) { + if ( aLVC.m_shieldZPart[iz]> z1 && aLVC.m_shieldZPart[iz] < z2 ) { + zSteps.push_back(aLVC.m_shieldZPart[iz]); + z1 = aLVC.m_shieldZPart[iz]; + } + } + zSteps.push_back(z2); + + // phi binning trivial + aLVC.m_adjustedPhi.clear(); + aLVC.m_adjustedPhi.push_back(0.); + + unsigned int etaN = zSteps.size()-1; + + // create z,h bin utilities + //Trk::BinUtility1DZZ* zBinUtil = new Trk::BinUtility1DZZ(zSteps); + //Trk::BinUtility1DF* pBinUtil = new Trk::BinUtility1DF(m_adjustedPhi); + Trk::BinUtility* zBinUtil = new Trk::BinUtility(zSteps, Trk::BinningOption::open, Trk::BinningValue::binZ ); + //Trk::BinUtility* pBinUtil = new Trk::BinUtility(m_adjustedPhi, Trk::BinningOption::closed, Trk::BinningValue::binPhi ); + Trk::BinUtility* pBinUtil = new Trk::BinUtility( 1, -M_PI, M_PI, Trk::BinningOption::closed, Trk::BinningValue::binPhi ); + std::vector<std::vector<Trk::BinUtility*> >* hBinUtil=new std::vector<std::vector<Trk::BinUtility*> >; + float phiRef = 0.; + for (unsigned iz=0;iz < zSteps.size()-1; iz++) { + std::vector<Trk::BinUtility*> phBinUtil; + phBinUtil.push_back(new Trk::BinUtility(phiRef,aLVC.m_shieldHPart[type]) ); + hBinUtil->push_back(phBinUtil); + } + + // subvolume boundaries + Trk::CylinderVolumeBounds* subBds=0; + + // create subvolumes & BinnedArray + std::vector<Trk::TrackingVolumeOrderPosition> subVolumesVect; + std::vector<std::vector<std::vector<const Trk::TrackingVolume*> > > subVolumes; + std::vector<std::vector<Trk::SharedObject<Trk::BinnedArray<Trk::TrackingVolume> > > > hBins; + std::vector<const Trk::TrackingVolume*> sVolsInn; // for gluing + std::vector<const Trk::TrackingVolume*> sVolsOut; // for gluing + std::vector<const Trk::TrackingVolume*> sVolsNeg; // for gluing + std::vector<const Trk::TrackingVolume*> sVolsPos; // for gluing + for (unsigned int eta = 0; eta < zSteps.size()-1; eta++) { + if (colorCode>0) colorCode = 26 -colorCode; + double posZ = 0.5*(zSteps[eta] + zSteps[eta+1]) ; + double hZ = 0.5*fabs(zSteps[eta+1] - zSteps[eta]) ; + std::vector<std::vector<const Trk::TrackingVolume*> > phiSubs; + std::vector<Trk::SharedObject<Trk::BinnedArray<Trk::TrackingVolume> > > phBins; + int phi = 0; + double posPhi = 0.; + double phiSect = M_PI; + std::vector<std::pair<int,float> > hSteps = aLVC.m_shieldHPart[type]; + std::vector<const Trk::TrackingVolume*> hSubs; + std::vector<Trk::TrackingVolumeOrderPosition> hSubsTr; + unsigned int hCode = 1; + for (unsigned int h = 0; h < hSteps.size()-1; h++) { + hCode = (colorCode>0) ? 1 - hCode : 0; + // define subvolume + subBds = new Trk::CylinderVolumeBounds(hSteps[h].second, + hSteps[h+1].second, + phiSect, + hZ); + Amg::Transform3D* transf = new Amg::Transform3D(Amg::AngleAxis3D(posPhi,Amg::Vector3D(0.,0.,1.))*Amg::Translation3D(Amg::Vector3D(0.,0.,posZ))); + Trk::Volume subVol(transf, subBds); + + // enclosed muon objects ? also adjusts material properties in case of material blend + std::string volName = volumeName +MuonGM::buildString(eta,2) +MuonGM::buildString(phi,2) +MuonGM::buildString(h,2) ; + blendVols.clear(); + std::vector<const Trk::DetachedTrackingVolume*>* detVols= getDetachedObjects( &subVol, blendVols,aLVC); + + const Trk::TrackingVolume* sVol = new Trk::TrackingVolume( subVol, + aLVC.m_muonMaterial, + detVols, + volName ); + + // statistics + m_frameNum++ ; if (detVols) m_frameStat += detVols->size(); + // prepare blending + if (m_blendInertMaterial && blendVols.size()) { + for (unsigned int id=0;id<blendVols.size();id++) { + if (!aLVC.m_blendMap[blendVols[id]]) { + aLVC.m_blendMap[blendVols[id]] = new std::vector<const Trk::TrackingVolume*>; + aLVC.m_blendVols.push_back(blendVols[id]); + } + aLVC.m_blendMap[blendVols[id]]->push_back(sVol); + } + } + // reference point for the check of envelope + double posR = 0.5*(hSteps[h].second+hSteps[h+1].second); + // loop over inner cutouts + for (unsigned int in=1; in<aLVC.m_msCutoutsIn.size(); in++) { + if (posZ>=aLVC.m_msCutoutsIn[in].second && posZ<=aLVC.m_msCutoutsIn[in-1].second) { + if (posR < aLVC.m_msCutoutsIn[in].first) sVol->sign(Trk::BeamPipe); + break; + } + } + // + sVol->registerColorCode(colorCode+hCode); + // reference position + Amg::Vector3D gp(subBds->mediumRadius(),0.,0.); + subVolumesVect.push_back(Trk::TrackingVolumeOrderPosition(Trk::SharedObject<const Trk::TrackingVolume>(sVol), + Amg::Vector3D((*transf)*gp))); + hSubsTr.push_back(Trk::TrackingVolumeOrderPosition(Trk::SharedObject<const Trk::TrackingVolume>(sVol, Trk::do_not_delete<const Trk::TrackingVolume>), + Amg::Vector3D((*transf)*gp))); + hSubs.push_back(sVol); + + //glue subVolume + if (h==0) sVolsInn.push_back(sVol); + if (h==hSteps.size()-2) sVolsOut.push_back(sVol); + if (eta==0) sVolsNeg.push_back(sVol); + if (eta==etaN-1) sVolsPos.push_back(sVol); + // in R/H + if (h>0) { // glue 'manually' + m_trackingVolumeHelper->setInsideTrackingVolume(*sVol, Trk::tubeSectorInnerCover,hSubs[h-1]); + m_trackingVolumeHelper->setOutsideTrackingVolume(*(hSubs[h-1]), Trk::tubeSectorOuterCover,sVol); + } + // in eta + if ( etaN>1 && eta>0) m_trackingVolumeHelper->setOutsideTrackingVolumeArray(*sVol, Trk::negativeFaceXY, hBins[eta-1][phi]); + } + phiSubs.push_back(hSubs); + Trk::BinnedArray1D<Trk::TrackingVolume>* volBinArray = new Trk::BinnedArray1D<Trk::TrackingVolume>(hSubsTr,(*hBinUtil)[eta][phi]->clone()); + phBins.push_back(Trk::SharedObject<Trk::BinnedArray<Trk::TrackingVolume> >(volBinArray)); + + // finish eta gluing + if ( etaN>1 && eta>0) { + for (unsigned int j=0; j<subVolumes[eta-1][phi].size(); j++) { + m_trackingVolumeHelper->setOutsideTrackingVolumeArray(*(subVolumes[eta-1][phi][j]), Trk::positiveFaceXY,phBins[phi]); + } + } + subVolumes.push_back(phiSubs); + hBins.push_back(phBins); + } + + //Trk::BinUtility3DZFH* volBinUtil=new Trk::BinUtility3DZFH(zBinUtil,pBinUtil,hBinUtil,new Amg::Transform3D(vol->transform())); + + Trk::BinnedArray1D1D1D<Trk::TrackingVolume>* subVols=new Trk::BinnedArray1D1D1D<Trk::TrackingVolume>(subVolumesVect,zBinUtil,pBinUtil,hBinUtil); + + tVol = new Trk::TrackingVolume( *vol, + aLVC.m_muonMaterial, + 0,subVols, + volumeName); + // register glue volumes + const Trk::GlueVolumesDescriptor& volGlueVolumes = tVol->glueVolumesDescriptor(); + volGlueVolumes.registerGlueVolumes(Trk::tubeInnerCover,sVolsInn); + volGlueVolumes.registerGlueVolumes(Trk::tubeOuterCover,sVolsOut); + volGlueVolumes.registerGlueVolumes(Trk::negativeFaceXY,sVolsNeg); + volGlueVolumes.registerGlueVolumes(Trk::positiveFaceXY,sVolsPos); + + return tVol; +} + +std::vector<const Trk::DetachedTrackingVolume*>* Muon::MuonTrackingGeometryBuilderCond::getDetachedObjects(const Trk::Volume* vol, std::vector<const Trk::DetachedTrackingVolume*>& blendVols, LocalVariablesContainer &aLVC, int mode ) const +{ + // mode : 0 all, 1 active only, 2 inert only + + std::vector<const Trk::DetachedTrackingVolume*>* detTVs = 0; + + if (!m_stations && !m_inertObjs) return detTVs; + + // get min/max Z/Phi from volume (allways a cylinder/bevelled cylinder volume ) + const Trk::CylinderVolumeBounds* cyl = dynamic_cast<const Trk::CylinderVolumeBounds*> (&(vol->volumeBounds())); + const Trk::BevelledCylinderVolumeBounds* bcyl = dynamic_cast<const Trk::BevelledCylinderVolumeBounds*> (&(vol->volumeBounds())); + + double rmed = 0.; double dphi = 0.; double hz = 0.; double rMin = 0.; double rMax = 0.; double rMaxc = 0.; int type = 0; + if (cyl) { + rmed = cyl->mediumRadius(); + dphi = cyl->halfPhiSector(); + hz = cyl->halflengthZ(); + rMin = cyl->innerRadius(); + rMax = cyl->outerRadius(); + rMaxc = rMax; + } else if (bcyl) { + rmed = bcyl->mediumRadius(); + dphi = bcyl->halfPhiSector(); + hz = bcyl->halflengthZ(); + rMin = bcyl->innerRadius(); + rMax = bcyl->outerRadius(); + rMaxc = rMax; + type = bcyl->type(); + if (type>1) rMaxc *=1./cos(dphi); + } else return 0; + + Amg::Vector3D center(rmed,0.,0.); + center = vol->transform() * center; + + double zMin = center[2] - hz; + double zMax = center[2] + hz; + double pMin = 0.; + double pMax = +2*M_PI; + bool phiLim = false; + if (dphi < M_PI) { + pMin = center.phi() - dphi + M_PI; + pMax = center.phi() + dphi + M_PI; + phiLim = true; + } + + ATH_MSG_VERBOSE( " zMin "<< zMin <<" zMax " <<zMax << " rMin "<< rMin <<" rMax "<<rMax << " rMaxc " << rMaxc << " phi limits "<< pMin <<" phiMax "<<pMax << " phiLim " << phiLim); + + // define detector region : can extend over several + int gMin = (zMax <= -m_bigWheel) ? 0 : 1; + if ( zMin >= m_bigWheel ) gMin = 8; + else if ( zMin >= aLVC.m_innerEndcapZ ) gMin = 7; + else if ( zMin >= m_ectZ ) gMin = 6; + else if ( zMin >= m_diskShieldZ ) gMin = 5; + else if ( zMin >=-m_diskShieldZ ) gMin = 4; + else if ( zMin >=-m_ectZ ) gMin = 3; + else if ( zMin >=-aLVC.m_innerEndcapZ ) gMin = 2; + int gMax = (zMax >= m_bigWheel) ? 8 : 7; + if ( zMax <= -m_bigWheel ) gMax = 0; + else if ( zMax <= -aLVC.m_innerEndcapZ ) gMax = 1; + else if ( zMax <= -m_ectZ ) gMax = 2; + else if ( zMax <= -m_diskShieldZ ) gMax = 3; + else if ( zMax <= m_diskShieldZ ) gMax = 4; + else if ( zMax <= m_ectZ ) gMax = 5; + else if ( zMax <= aLVC.m_innerEndcapZ ) gMax = 6; + + ATH_MSG_VERBOSE( " active volumes gMin "<< gMin<<" gMax "<<gMax); + + std::list<const Trk::DetachedTrackingVolume*> detached; + // active, use corrected rMax + if (mode <2 && aLVC.m_stationSpan) { + for (int gMode=gMin; gMode<=gMax; gMode++) { + for (unsigned int i=0; i<(*aLVC.m_stationSpan)[gMode]->size() ; i++) { + const Muon::Span* s = (*((*aLVC.m_stationSpan)[gMode]))[i].second; // span + const Trk::DetachedTrackingVolume* station = (*((*aLVC.m_stationSpan)[gMode]))[i].first; // station + bool rLimit = !aLVC.m_static3d || ( (*s)[4] <= rMaxc && (*s)[5] >= rMin ); +// Check meanZ for BME stations + bool meanZOK = false; + if(station->name()=="BME1_Station"||station->name()=="BME2_Station") { + if( ((*s)[0]+(*s)[1])/2.< zMax&&((*s)[0]+(*s)[1])/2.> zMin ) meanZOK = true; + if( ((*s)[2]+(*s)[3])/2 <pMin&&phiLim) meanZOK = false; + if( ((*s)[2]+(*s)[3])/2 <pMin&&phiLim) meanZOK = false; + } + if ( rLimit && (((*s)[0] < zMax && (*s)[1] > zMin)||meanZOK) ) { + bool accepted = false; + if (phiLim) { + if (pMin>=0 && pMax<=2*M_PI) { + if ( (*s)[2]<=(*s)[3] && (*s)[2] <= pMax && (*s)[3] >= pMin ) accepted = true; + if ( (*s)[2]>(*s)[3] && ((*s)[2] <= pMax || (*s)[3] >= pMin) ) accepted = true; + } else if (pMin < 0) { + if ( (*s)[2]<=(*s)[3] && ((*s)[2] <= pMax || (*s)[3] >= pMin+2*M_PI) ) accepted = true; + if ( (*s)[2]>(*s)[3] ) accepted = true; + } else if (pMax > 2*M_PI) { + if ( (*s)[2]<=(*s)[3] && ((*s)[2] <= pMax-2*M_PI || (*s)[3] >= pMin) ) accepted = true; + if ( (*s)[2]>(*s)[3] ) accepted = true; + } + } else accepted = true; + if(meanZOK) accepted = true; + if (accepted) { + detached.push_back(station); + ATH_MSG_VERBOSE(" active volume accepted by rLimit " << station->name() << " zMin " << zMin << " zMax " << zMax << " rMin " << rMin << " rMax " << rMax << " PhiMin " << pMin << " PhiMax " << pMax); + } + } else { +// ATH_MSG_VERBOSE( " active volume rejected by rLimit " << station->name() ); + } + } + } + } + // passive + if (mode !=1 && aLVC.m_inertSpan) { + for (int gMode=gMin; gMode<=gMax; gMode++) { + for (unsigned int i=0; i<(*aLVC.m_inertSpan)[gMode]->size() ; i++) { + const Muon::Span* s = (*((*aLVC.m_inertSpan)[gMode]))[i].second; + const Trk::DetachedTrackingVolume* inert = (*((*aLVC.m_inertSpan)[gMode]))[i].first; + //bool rail = ( (*m_inertObjs)[i]->name() == "Rail" ) ? true : false; + bool rLimit = (!aLVC.m_static3d || ( (*s)[4] <= rMaxc && (*s)[5] >= rMin ) ); + if ( rLimit && (*s)[0] < zMax && (*s)[1] > zMin ) { + bool accepted = false; + if (phiLim) { + if (pMin>=0 && pMax<=2*M_PI) { + if ( (*s)[2]<=(*s)[3] && (*s)[2] <= pMax && (*s)[3] >= pMin ) accepted = true; + if ( (*s)[2]>(*s)[3] && ((*s)[2] <= pMax || (*s)[3] >= pMin) ) accepted = true; + } else if (pMin < 0) { + if ( (*s)[2]<=(*s)[3] && ((*s)[2] <= pMax || (*s)[3] >= pMin+2*M_PI) ) accepted = true; + if ( (*s)[2]>(*s)[3] ) accepted = true; + } else if (pMax > 2*M_PI) { + if ( (*s)[2]<=(*s)[3] && ((*s)[2] <= pMax-2*M_PI || (*s)[3] >= pMin) ) accepted = true; + if ( (*s)[2]>(*s)[3] ) accepted = true; + } + } else accepted = true; + if (accepted) { + bool perm = inert->name().substr(inert->name().size()-4,4)=="PERM"; + if ( !m_blendInertMaterial || !m_removeBlended || perm ) detached.push_back(inert); + if ( m_blendInertMaterial && !perm ) blendVols.push_back(inert); + ATH_MSG_VERBOSE( " Inert volume accepted by rLimit " << inert->name() << " zMin " << zMin << " zMax " << zMax << " rMin " << rMin << " rMax " << rMax << " PhiMin " << pMin << " PhiMax " << pMax); + } + } + } + } + } + if (!detached.empty()) detTVs = new std::vector<const Trk::DetachedTrackingVolume*>(detached.begin(), detached.end()); + return detTVs; +} + +bool Muon::MuonTrackingGeometryBuilderCond::enclosed(const Trk::Volume* vol, const Muon::Span* s, LocalVariablesContainer &aLVC) const +{ + bool encl = false; + double tol = 1.; + double ptol = 0.11; // 0.08 for BT, 0.11 feet + + // get min/max Z/Phi from volume (allways a cylinder/bevelled cylinder volume ) + const Trk::CylinderVolumeBounds* cyl = dynamic_cast<const Trk::CylinderVolumeBounds*> (&(vol->volumeBounds())); + const Trk::BevelledCylinderVolumeBounds* bcyl = dynamic_cast<const Trk::BevelledCylinderVolumeBounds*> (&(vol->volumeBounds())); + + double rmed = 0.; double dphi = 0.; double hz = 0.; double rMin = 0.; double rMax = 0.; double rMaxc = 0.; int type = 0; + if (cyl) { + rmed = cyl->mediumRadius(); + dphi = cyl->halfPhiSector(); + hz = cyl->halflengthZ(); + rMin = cyl->innerRadius(); + rMax = cyl->outerRadius(); + rMaxc = rMax; + } else if (bcyl) { + rmed = bcyl->mediumRadius(); + dphi = bcyl->halfPhiSector(); + hz = bcyl->halflengthZ(); + rMin = bcyl->innerRadius(); + rMax = bcyl->outerRadius(); + rMaxc = rMax; + type = bcyl->type(); + if (type>1) rMaxc *=1./cos(dphi); + } else return 0; + + Amg::Vector3D center(rmed,0.,0.); + center = vol->transform() * center; + + double zMin = center[2] - hz; + double zMax = center[2] + hz; + double pMin = 0.; + double pMax = +2*M_PI; + bool phiLim = false; + if (dphi < M_PI) { + pMin = center.phi() - dphi + M_PI; + pMax = center.phi() + dphi + M_PI; + phiLim = true; + } + // + //const Muon::Span* s = findVolumeSpan(&(cs->volumeBounds()), cs->transform(), 0.,0.) ; + //std::auto_ptr<const Muon::Span> s (findVolumeSpan(&(cs->volumeBounds()), cs->transform(), 0.,0.) ); + ATH_MSG_VERBOSE( "enclosing volume:z:"<< zMin<<","<<zMax<<":r:"<< rMin<<","<<rMax<<":phi:"<<pMin<<","<<pMax); + // + bool rLimit = (!aLVC.m_static3d || ( (*s)[4] < rMax-tol && (*s)[5] > rMin+tol ) ); + if ( rLimit && (*s)[0] < zMax-tol && (*s)[1] > zMin+tol ) { + if (phiLim) { + if (pMin>=0 && pMax<=2*M_PI) { + if ( (*s)[2]<=(*s)[3] && (*s)[2] < pMax+ptol && (*s)[3] > pMin-ptol ) return true; + if ( (*s)[2]>(*s)[3] && ((*s)[2] < pMax-ptol || (*s)[3] > pMin+ptol) ) return true; + } else if (pMin < 0) { + if ( (*s)[2]<=(*s)[3] && ((*s)[2] < pMax+ptol || (*s)[3] > pMin-ptol+2*M_PI) ) return true; + if ( (*s)[2]>(*s)[3] ) return true; + } else if (pMax > 2*M_PI) { + if ( (*s)[2]<=(*s)[3] && ((*s)[2] < pMax+ptol-2*M_PI || (*s)[3] > pMin-ptol) ) return true; + if ( (*s)[2]>(*s)[3] ) return true; + } + } else { + return true; + } + } + return encl; +} + +void Muon::MuonTrackingGeometryBuilderCond::checkVolume(const Trk::TrackingVolume* vol ) const +{ + + std::cout << "MuonTrackingGeometryBuilderCond::checkVolume: " << vol->volumeName() << std::endl; + + const Trk::CylinderVolumeBounds* cyl = dynamic_cast<const Trk::CylinderVolumeBounds*> (&(vol->volumeBounds())); + if (!cyl) { + std::cout << "MuonTrackingGeometryBuilderCond::checkVolume:not a cylinder, return" << std::endl; + return; + } + std::cout << "cylinder dimensions:innerR,outerR,halfZ,halfPhi:" << cyl->innerRadius() << "," << cyl->outerRadius() + << cyl->halflengthZ() << "," << cyl->halfPhiSector() << std::endl; + + const Trk::GlueVolumesDescriptor& glueDescr = vol->glueVolumesDescriptor(); + std::cout << "glue volumes:neg,pos,inn,outer" << (glueDescr.glueVolumes(Trk::negativeFaceXY)).size()<<"," + << (glueDescr.glueVolumes(Trk::positiveFaceXY)).size()<<"," + << (glueDescr.glueVolumes(Trk::tubeInnerCover)).size()<<"," + << (glueDescr.glueVolumes(Trk::tubeOuterCover)).size()<<std::endl; +} + +void Muon::MuonTrackingGeometryBuilderCond::getZParts(LocalVariablesContainer& aLVC) const +{ + // activeAdjustLevel: 1: separate MDT stations + // +(inertLevel=0) barrel Z partition + // 2: split TGC + // +(inertLevel=0) barrel R partition + // 3: split TGC supports + // inertAdjustLevel: 1: BT,ECT + + // hardcode for the moment + aLVC.m_zPartitions.clear(); + aLVC.m_zPartitionsType.clear(); + aLVC.m_zPartitions.reserve(120); + aLVC.m_zPartitionsType.reserve(120); + + // outer endcap + aLVC.m_zPartitions.push_back(-aLVC.m_outerEndcapZ); aLVC.m_zPartitionsType.push_back(1); // EO + aLVC.m_zPartitions.push_back(-23001.); aLVC.m_zPartitionsType.push_back(1); // oute envelope change + //if (m_activeAdjustLevel>0) { m_zPartitions.push_back(-21630.); m_zPartitionsType.push_back(1); } // EOL + aLVC.m_zPartitions.push_back(-22030.); aLVC.m_zPartitionsType.push_back(1); // EOL + aLVC.m_zPartitions.push_back(-m_outerWheel); aLVC.m_zPartitionsType.push_back(0); // Octogon + // m_zPartitions.push_back(-17990.); m_zPartitionsType.push_back(0); // buffer + aLVC.m_zPartitions.push_back(-18650.); aLVC.m_zPartitionsType.push_back(0); // buffer + aLVC.m_zPartitions.push_back(-m_bigWheel); aLVC.m_zPartitionsType.push_back(1); // TGC3 + if (m_activeAdjustLevel>2) { aLVC.m_zPartitions.push_back(-15225.); aLVC.m_zPartitionsType.push_back(1);} + if (m_activeAdjustLevel>1) { aLVC.m_zPartitions.push_back(-15172.); aLVC.m_zPartitionsType.push_back(1);} // end supp + if (m_activeAdjustLevel>2) { aLVC.m_zPartitions.push_back(-15128.); aLVC.m_zPartitionsType.push_back(1);} // supp + if (m_activeAdjustLevel>2) { aLVC.m_zPartitions.push_back(-15070.); aLVC.m_zPartitionsType.push_back(1);} + if (m_activeAdjustLevel>0) { aLVC.m_zPartitions.push_back(-14940.); aLVC.m_zPartitionsType.push_back(1); } // + if (m_activeAdjustLevel>2) { aLVC.m_zPartitions.push_back(-14805.); aLVC.m_zPartitionsType.push_back(1);} + if (m_activeAdjustLevel>1) { aLVC.m_zPartitions.push_back(-14733.); aLVC.m_zPartitionsType.push_back(1);} // end supp. + if (m_activeAdjustLevel>2) { aLVC.m_zPartitions.push_back(-14708.); aLVC.m_zPartitionsType.push_back(1);} // supp. + if (m_activeAdjustLevel>2) { aLVC.m_zPartitions.push_back(-14650.); aLVC.m_zPartitionsType.push_back(1);} // + if (m_activeAdjustLevel>0) { aLVC.m_zPartitions.push_back(-14560.); aLVC.m_zPartitionsType.push_back(1); } // EML + if (m_activeAdjustLevel>0) { aLVC.m_zPartitions.push_back(-14080.); aLVC.m_zPartitionsType.push_back(1); } // EMS + if (m_activeAdjustLevel>0) { aLVC.m_zPartitions.push_back(-13620.); aLVC.m_zPartitionsType.push_back(1); } // TGC + if (m_activeAdjustLevel>2) { aLVC.m_zPartitions.push_back(-13525.); aLVC.m_zPartitionsType.push_back(1); } // TGC + if (m_activeAdjustLevel>1) { aLVC.m_zPartitions.push_back(-13448.5); aLVC.m_zPartitionsType.push_back(1); } // end supp. + if (m_activeAdjustLevel>2) { aLVC.m_zPartitions.push_back(-13421.5); aLVC.m_zPartitionsType.push_back(1); } // supp. + if (m_activeAdjustLevel>2) { aLVC.m_zPartitions.push_back(-13346); aLVC.m_zPartitionsType.push_back(1); } // TGC + + // inner endcap + aLVC.m_zPartitions.push_back(-aLVC.m_innerEndcapZ); aLVC.m_zPartitionsType.push_back(0); // + if (m_inertAdjustLevel>0) { aLVC.m_zPartitions.push_back(-12790); aLVC.m_zPartitionsType.push_back(0); } // ECT + if (m_inertAdjustLevel>1) { aLVC.m_zPartitions.push_back(-12100.); aLVC.m_zPartitionsType.push_back(0); } // + if (m_inertAdjustLevel>0) { aLVC.m_zPartitions.push_back(-12000.); aLVC.m_zPartitionsType.push_back(0); } // + if (m_inertAdjustLevel>0) { aLVC.m_zPartitions.push_back(-11210.); aLVC.m_zPartitionsType.push_back(1); } // BT + if (m_inertAdjustLevel>0) { aLVC.m_zPartitions.push_back(-10480.); aLVC.m_zPartitionsType.push_back(0); } // + if (m_inertAdjustLevel>0) { aLVC.m_zPartitions.push_back(-9700.); aLVC.m_zPartitionsType.push_back(0); } // + if (m_inertAdjustLevel>1) { aLVC.m_zPartitions.push_back(-9300.); aLVC.m_zPartitionsType.push_back(0); } // rib + if (m_inertAdjustLevel>1) { aLVC.m_zPartitions.push_back(-8800.); aLVC.m_zPartitionsType.push_back(0); } // ect + if (m_inertAdjustLevel>0) { aLVC.m_zPartitions.push_back(-8610.); aLVC.m_zPartitionsType.push_back(1); } // BT + if (m_inertAdjustLevel>0) { aLVC.m_zPartitions.push_back(-8000.); aLVC.m_zPartitionsType.push_back(1); } // BT + aLVC.m_zPartitions.push_back(-m_ectZ); aLVC.m_zPartitionsType.push_back(0); // ECT/small wheel + if (m_activeAdjustLevel>0) { aLVC.m_zPartitions.push_back(-7450.); aLVC.m_zPartitionsType.push_back(0); } // EIS + if (m_activeAdjustLevel>2) { aLVC.m_zPartitions.push_back(-7364.); aLVC.m_zPartitionsType.push_back(0); } // EIS + if (m_activeAdjustLevel>0 || m_inertAdjustLevel>0) {aLVC.m_zPartitions.push_back(-7170.); aLVC.m_zPartitionsType.push_back(0);} // cone assembly,TGC + if (m_activeAdjustLevel>0) { aLVC.m_zPartitions.push_back(-7030.); aLVC.m_zPartitionsType.push_back(0); } // TGC + if (m_activeAdjustLevel>2) { aLVC.m_zPartitions.push_back(-6978.); aLVC.m_zPartitionsType.push_back(0); } // TGC + + // barrel + aLVC.m_zPartitions.push_back(-m_diskShieldZ); aLVC.m_zPartitionsType.push_back(0); // disk + if (m_inertAdjustLevel>0) { aLVC.m_zPartitions.push_back(-6829.); aLVC.m_zPartitionsType.push_back(0); } // back disk + //if (m_inertAdjustLevel>1) { (*m_zPartitions).push_back(-6600.); m_zPartitionsType.push_back(0); } // + aLVC.m_zPartitions.push_back(-6550.); aLVC.m_zPartitionsType.push_back(0); // outer envelope change + if (m_activeAdjustLevel>0){ aLVC.m_zPartitions.push_back(-6100.); aLVC.m_zPartitionsType.push_back(0); } + if (m_inertAdjustLevel>0) { aLVC.m_zPartitions.push_back(-5503.); aLVC.m_zPartitionsType.push_back(1); } // BT + if (m_inertAdjustLevel>0) { aLVC.m_zPartitions.push_back(-4772.); aLVC.m_zPartitionsType.push_back(0); } // + if (m_activeAdjustLevel>0){ aLVC.m_zPartitions.push_back(-4300.); aLVC.m_zPartitionsType.push_back(0); } // + aLVC.m_zPartitions.push_back(-4000.); aLVC.m_zPartitionsType.push_back(0); // outer envelope change + if (m_inertAdjustLevel>1) { aLVC.m_zPartitions.push_back(-3700.); aLVC.m_zPartitionsType.push_back(0); } // + if (m_inertAdjustLevel>1) { aLVC.m_zPartitions.push_back(-3300.); aLVC.m_zPartitionsType.push_back(0); } // + if (m_activeAdjustLevel>0){ aLVC.m_zPartitions.push_back(-2600.); aLVC.m_zPartitionsType.push_back(0); } // + if (m_inertAdjustLevel>0) { aLVC.m_zPartitions.push_back(-2078.); aLVC.m_zPartitionsType.push_back(1); } // BT + if (m_inertAdjustLevel>0) { aLVC.m_zPartitions.push_back(-1347.); aLVC.m_zPartitionsType.push_back(1); } // cryoring + if (m_activeAdjustLevel>0){ aLVC.m_zPartitions.push_back(-800.); aLVC.m_zPartitionsType.push_back(1); } // cryoring + if (m_inertAdjustLevel>1) { aLVC.m_zPartitions.push_back(-300.); aLVC.m_zPartitionsType.push_back(0); } // + if (static_cast<int>(m_inertAdjustLevel)+static_cast<int>(m_activeAdjustLevel)<1) { aLVC.m_zPartitions.push_back(-0.7*m_diskShieldZ); aLVC.m_zPartitionsType.push_back(0); } // + + unsigned int zSiz = aLVC.m_zPartitions.size(); + for (unsigned int i = 0; i<zSiz ; i++) { + aLVC.m_zPartitions.push_back(- aLVC.m_zPartitions[zSiz-1-i]); + if (i<zSiz-1) aLVC.m_zPartitionsType.push_back(aLVC.m_zPartitionsType[zSiz-2-i]); + } + + return; +} + +void Muon::MuonTrackingGeometryBuilderCond::getPhiParts(int mode, LocalVariablesContainer &aLVC) const +{ + if (mode==0) { // trivial + aLVC.m_adjustedPhi.clear(); + aLVC.m_adjustedPhiType.clear(); + aLVC.m_adjustedPhi.push_back(0.); + aLVC.m_adjustedPhiType.push_back(0); + + } else if (mode==1) { + int phiNum = 1; + if ( m_activeAdjustLevel>0 ) phiNum = m_phiPartition; + aLVC.m_adjustedPhi.resize(phiNum); + aLVC.m_adjustedPhiType.resize(phiNum); + aLVC.m_adjustedPhi[0] = 0.; + aLVC.m_adjustedPhiType[0] = 0; + int ic = 0; + while (ic < phiNum-1 ) { + ic++; + aLVC.m_adjustedPhi[ic]= aLVC.m_adjustedPhi[ic-1] + 2.*M_PI/phiNum ; + aLVC.m_adjustedPhiType[ic]= 0; + } + + } else if (mode==2) { // barrel(BT) + // hardcode for the moment + aLVC.m_adjustedPhi.resize(16); + aLVC.m_adjustedPhiType.resize(16); + + double phiSect[2]; + phiSect[0] = ( M_PI/8 - 0.105 ); + phiSect[1] = 0.105 ; + + aLVC.m_adjustedPhi[0]= - phiSect[0]; + aLVC.m_adjustedPhiType[0]= 0; + int ic = 0; int is = 1; + + while (ic < 15 ) { + ic++; is = 1 - is; + aLVC.m_adjustedPhi[ic]= aLVC.m_adjustedPhi[ic-1] + 2*phiSect[is] ; + aLVC.m_adjustedPhiType[ic]= 1-is; + } + + } else if (mode==3) { // ECT(+BT) + // hardcode for the moment + aLVC.m_adjustedPhi.resize(32); + aLVC.m_adjustedPhiType.resize(32); + + double phiSect[3]; + phiSect[0] = 0.126; + phiSect[2] = 0.105; + phiSect[1] = 0.5*( M_PI/8. - phiSect[0]-phiSect[2] ); + + aLVC.m_adjustedPhi[0]= - phiSect[0]; + aLVC.m_adjustedPhiType[0]= 0; + aLVC.m_adjustedPhi[1]= aLVC.m_adjustedPhi[0]+2*phiSect[0]; + aLVC.m_adjustedPhiType[1]= 1; + int ic = 1; int is = 0; + + while (ic < 31 ) { + ic++; is = 2 - is; + aLVC.m_adjustedPhi[ic]= aLVC.m_adjustedPhi[ic-1] + 2*phiSect[1] ; + aLVC.m_adjustedPhiType[ic]= is; + ic++; + aLVC.m_adjustedPhi[ic]= aLVC.m_adjustedPhi[ic-1] + 2*phiSect[is] ; + aLVC.m_adjustedPhiType[ic]= 1; + } + //for (unsigned int ic=0;ic<m_adjustedPhi.size();ic++) std::cout<<"adjustedPhi:"<<ic<<","<<m_adjustedPhi[ic]<<","<<m_adjustedPhiType[ic]<< std::endl; + } + + return; +} + +void Muon::MuonTrackingGeometryBuilderCond::getHParts(LocalVariablesContainer &aLVC) const +{ + // hardcode for the moment + aLVC.m_hPartitions.clear(); // barrel, inner endcap, outer endcap + + // 0: barrel 2x2 + // non BT sector + std::vector<std::pair<int,float> > barrelZ0F0; + barrelZ0F0.push_back( std::pair<int,float>(0,aLVC.m_innerBarrelRadius) ); + if (m_activeAdjustLevel>0) { + barrelZ0F0.push_back( std::pair<int,float>(0,4450.) ); // for DiskShieldingBackDisk + barrelZ0F0.push_back( std::pair<int,float>(0,6500.) ); // BI/BM + barrelZ0F0.push_back( std::pair<int,float>(0,8900.) ); // BM/BO + barrelZ0F0.push_back( std::pair<int,float>(0,13000.) ); // outer envelope + } + barrelZ0F0.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + std::vector<std::pair<int,float> > barrelZ0F1; + barrelZ0F1.push_back( std::pair<int,float>(0,aLVC.m_innerBarrelRadius) ); + if (m_inertAdjustLevel>0) { + barrelZ0F1.push_back( std::pair<int,float>(1,4500.) ); + barrelZ0F1.push_back( std::pair<int,float>(1,5900.) ); + } else if (m_activeAdjustLevel>0) barrelZ0F1.push_back( std::pair<int,float>(0,4450.) ); + if (m_activeAdjustLevel>0) barrelZ0F1.push_back( std::pair<int,float>(0,6500.) ); + if (m_inertAdjustLevel>0) barrelZ0F1.push_back( std::pair<int,float>(1,8900.) ); + else if (m_activeAdjustLevel>0) barrelZ0F1.push_back( std::pair<int,float>(0,8900.) ); + if (m_inertAdjustLevel>0) barrelZ0F1.push_back( std::pair<int,float>(1,10100.) ); + barrelZ0F1.push_back( std::pair<int,float>(0,13000.) ); // outer envelope + barrelZ0F1.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + // BT sector + std::vector<std::pair<int,float> > barrelZ1F0; + barrelZ1F0.push_back( std::pair<int,float>(0,aLVC.m_innerBarrelRadius) ); + if (static_cast<int>(m_activeAdjustLevel)+static_cast<int>(m_inertAdjustLevel)>0) barrelZ1F0.push_back( std::pair<int,float>(0,4450.) ); + if (m_inertAdjustLevel>0) { + barrelZ1F0.push_back( std::pair<int,float>(1,5800.) ); + barrelZ1F0.push_back( std::pair<int,float>(1,6500.) ); + } else if (m_activeAdjustLevel>0) barrelZ1F0.push_back( std::pair<int,float>(0,6500.) ); + if (m_inertAdjustLevel>0) { + barrelZ1F0.push_back( std::pair<int,float>(1,6750.) ); + barrelZ1F0.push_back( std::pair<int,float>(1,8400.) ); + } + if (m_activeAdjustLevel>0) barrelZ1F0.push_back( std::pair<int,float>(0,8770.) ); // adapted for cryoring (from 8900) + if (m_inertAdjustLevel>0) barrelZ1F0.push_back( std::pair<int,float>(1,9850.) ); // adapted for cryoring (from 9600) + barrelZ1F0.push_back( std::pair<int,float>(0,13000.) ); // outer envelope + barrelZ1F0.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + std::vector<std::pair<int,float> > barrelZ1F1; + barrelZ1F1.push_back( std::pair<int,float>(0,aLVC.m_innerBarrelRadius) ); + if (m_inertAdjustLevel>0) { + barrelZ1F1.push_back( std::pair<int,float>(1,4500.) ); + barrelZ1F1.push_back( std::pair<int,float>(1,6000.) ); + } else if (m_activeAdjustLevel>0) barrelZ1F1.push_back( std::pair<int,float>(0,4450.) ); + if (m_activeAdjustLevel>0) barrelZ1F1.push_back( std::pair<int,float>(0,6500.) ); + if (m_inertAdjustLevel>0) barrelZ1F1.push_back( std::pair<int,float>(1,6800.) ); + if (m_inertAdjustLevel>0) { + barrelZ1F1.push_back( std::pair<int,float>(1,8900.) ); + barrelZ1F1.push_back( std::pair<int,float>(1,10100.) ); + } else if (m_activeAdjustLevel>0) barrelZ1F1.push_back( std::pair<int,float>(0,8900.) ); + barrelZ1F1.push_back( std::pair<int,float>(0,13000.) ); // outer envelope + barrelZ1F1.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + std::vector<std::vector<std::vector<std::pair<int,float> > > > barrelZF(2); + barrelZF[0].push_back(barrelZ0F0); + barrelZF[0].push_back(barrelZ0F1); + barrelZF[1].push_back(barrelZ1F0); + barrelZF[1].push_back(barrelZ1F1); + + // small wheel 1x2 ( no z BT sector) + // non BT sector + std::vector<std::pair<int,float> > swZ0F0; + swZ0F0.push_back( std::pair<int,float>(0,m_innerShieldRadius) ); + if (m_activeAdjustLevel>1) { + swZ0F0.push_back( std::pair<int,float>(0,2700.) ); + } + if (static_cast<int>(m_activeAdjustLevel)+static_cast<int>(m_inertAdjustLevel)>0) swZ0F0.push_back( std::pair<int,float>(0,4450.) ); + if (m_activeAdjustLevel>0) { + swZ0F0.push_back( std::pair<int,float>(0,6560.) ); // BI/BM + swZ0F0.push_back( std::pair<int,float>(0,8900.) ); // BM/BO + } + swZ0F0.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + // phi BT sector + std::vector<std::pair<int,float> > swZ0F1; + swZ0F1.push_back( std::pair<int,float>(0,m_innerShieldRadius) ); + if (m_activeAdjustLevel>1) swZ0F1.push_back( std::pair<int,float>(0,2700.) ); + if (static_cast<int>(m_inertAdjustLevel)+static_cast<int>(m_activeAdjustLevel)>0) swZ0F1.push_back( std::pair<int,float>(0,4450.) ); + if (m_inertAdjustLevel>0) swZ0F1.push_back( std::pair<int,float>(1,5900.) ); + if (m_activeAdjustLevel>0) swZ0F1.push_back( std::pair<int,float>(0,6560.) ); + if (m_inertAdjustLevel>0) { + swZ0F1.push_back( std::pair<int,float>(1,8900.) ); + swZ0F1.push_back( std::pair<int,float>(1,10100.) ); + } else if (m_activeAdjustLevel>0) swZ0F1.push_back( std::pair<int,float>(0,8900.) ); + swZ0F1.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + std::vector<std::vector<std::vector<std::pair<int,float> > > > swZF(1); + swZF[0].push_back(swZ0F0); + swZF[0].push_back(swZ0F1); + + // inner endcap/ECT 2x3 + // ect coil, non-BT z + std::vector<std::pair<int,float> > innerZ0F0; + innerZ0F0.push_back( std::pair<int,float>(0,m_innerShieldRadius) ); + if (m_inertAdjustLevel>0) innerZ0F0.push_back( std::pair<int,float>(0,1100.) ); + if (m_inertAdjustLevel>1) innerZ0F0.push_back( std::pair<int,float>(1,5150.) ); + if (m_inertAdjustLevel>0) innerZ0F0.push_back( std::pair<int,float>(1,5300.) ); + if (m_activeAdjustLevel>0) { + innerZ0F0.push_back( std::pair<int,float>(0,6500.) ); + innerZ0F0.push_back( std::pair<int,float>(0,8900.) ); + } + innerZ0F0.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + // coil gap, non-BT z + std::vector<std::pair<int,float> > innerZ0F1; + innerZ0F1.push_back( std::pair<int,float>(0,m_innerShieldRadius) ); + if (m_inertAdjustLevel>0) innerZ0F1.push_back( std::pair<int,float>(0,1100.) ); + if (m_inertAdjustLevel>1) { + innerZ0F1.push_back( std::pair<int,float>(1,1400.) ); + innerZ0F1.push_back( std::pair<int,float>(1,1685.) ); + } + if (m_inertAdjustLevel>0) { + innerZ0F1.push_back( std::pair<int,float>(1,4700.) ); + innerZ0F1.push_back( std::pair<int,float>(1,5900.) ); + } + if (m_activeAdjustLevel>0) { + innerZ0F1.push_back( std::pair<int,float>(0,6500.) ); + innerZ0F1.push_back( std::pair<int,float>(0,8900.) ); + } + innerZ0F1.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + // BT coil, no-BT z + std::vector<std::pair<int,float> > innerZ0F2; + innerZ0F2.push_back( std::pair<int,float>(0,m_innerShieldRadius) ); + if (m_inertAdjustLevel>0) innerZ0F2.push_back( std::pair<int,float>(0,1100.) ); + if (m_inertAdjustLevel>1) { + innerZ0F2.push_back( std::pair<int,float>(1,1400.) ); + innerZ0F2.push_back( std::pair<int,float>(1,1685.) ); + } + if (m_inertAdjustLevel>0) { + innerZ0F2.push_back( std::pair<int,float>(1,4450.) ); + innerZ0F2.push_back( std::pair<int,float>(1,5900.) ); + } + if (m_activeAdjustLevel>0) innerZ0F2.push_back( std::pair<int,float>(0,6500.) ); + if (m_inertAdjustLevel>0) { + innerZ0F2.push_back( std::pair<int,float>(1,8900.) ); + innerZ0F2.push_back( std::pair<int,float>(1,10100.) ); + } else if (m_activeAdjustLevel>0) innerZ0F2.push_back( std::pair<int,float>(0,8900.) ); + innerZ0F2.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + // ect coil, z BT sector + std::vector<std::pair<int,float> > innerZ1F0; + innerZ1F0.push_back( std::pair<int,float>(0,m_innerShieldRadius) ); + if (m_inertAdjustLevel>0) innerZ1F0.push_back( std::pair<int,float>(0,1100.) ); + if (m_inertAdjustLevel>1) innerZ1F0.push_back( std::pair<int,float>(1,5150.) ); + if (m_inertAdjustLevel>0) innerZ1F0.push_back( std::pair<int,float>(1,5300.) ); + if (m_inertAdjustLevel>0) innerZ1F0.push_back( std::pair<int,float>(1,5800.) ); + if (m_inertAdjustLevel>0) innerZ1F0.push_back( std::pair<int,float>(1,6750.) ); + else if (m_activeAdjustLevel>0) innerZ1F0.push_back( std::pair<int,float>(0,6500.) ); + if (m_inertAdjustLevel>0) { + innerZ1F0.push_back( std::pair<int,float>(1,8400.) ); + innerZ1F0.push_back( std::pair<int,float>(1,9600.) ); + } else if (m_activeAdjustLevel>0) innerZ1F0.push_back( std::pair<int,float>(0,8900.) ); + innerZ1F0.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + // coil gap, BT z sector + std::vector<std::pair<int,float> > innerZ1F1; + innerZ1F1.push_back( std::pair<int,float>(0,m_innerShieldRadius) ); + if (m_inertAdjustLevel>0) innerZ1F1.push_back( std::pair<int,float>(0,1100.) ); + if (m_inertAdjustLevel>1) { + innerZ1F1.push_back( std::pair<int,float>(1,1400.) ); + innerZ1F1.push_back( std::pair<int,float>(1,1685.) ); + } + if (m_inertAdjustLevel>0) { + innerZ1F1.push_back( std::pair<int,float>(1,4700.) ); + innerZ1F1.push_back( std::pair<int,float>(1,5800.) ); + innerZ1F1.push_back( std::pair<int,float>(1,6750.) ); + } else if (m_activeAdjustLevel>0) innerZ1F1.push_back( std::pair<int,float>(0,6500.) ); + if (m_inertAdjustLevel>0) { + innerZ1F1.push_back( std::pair<int,float>(1,8400.) ); + innerZ1F1.push_back( std::pair<int,float>(1,9600.) ); + } else if (m_activeAdjustLevel>0) innerZ1F1.push_back( std::pair<int,float>(0,8900.) ); + innerZ1F1.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + // BT coil, BT z sector + std::vector<std::pair<int,float> > innerZ1F2; + innerZ1F2.push_back( std::pair<int,float>(0,m_innerShieldRadius) ); + if (m_inertAdjustLevel>0) innerZ1F2.push_back( std::pair<int,float>(0,1100.) ); + if (m_inertAdjustLevel>1) { + innerZ1F2.push_back( std::pair<int,float>(1,1400.) ); + innerZ1F2.push_back( std::pair<int,float>(1,1685.) ); + } + innerZ1F2.push_back( std::pair<int,float>(0,4150.) ); + if (m_inertAdjustLevel>0) { + innerZ1F2.push_back( std::pair<int,float>(1,4700.) ); + innerZ1F2.push_back( std::pair<int,float>(1,5900.) ); + innerZ1F2.push_back( std::pair<int,float>(1,6800.) ); + } else if (m_activeAdjustLevel>0) innerZ1F2.push_back( std::pair<int,float>(0,6500.) ); + if (m_inertAdjustLevel>0) { + innerZ1F2.push_back( std::pair<int,float>(1,8900.) ); + innerZ1F2.push_back( std::pair<int,float>(1,10100.) ); + } else if (m_activeAdjustLevel>0) innerZ1F2.push_back( std::pair<int,float>(0,8900.) ); + innerZ1F2.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + std::vector<std::vector<std::vector<std::pair<int,float> > > > innerZF(2); + innerZF[0].push_back(innerZ0F0); + innerZF[0].push_back(innerZ0F1); + innerZF[0].push_back(innerZ0F2); + innerZF[1].push_back(innerZ1F0); + innerZF[1].push_back(innerZ1F1); + innerZF[1].push_back(innerZ1F2); + + // outer 1x1 + std::vector<std::pair<int,float> > outerZ0F0; + outerZ0F0.push_back( std::pair<int,float>(0,m_outerShieldRadius) ); + outerZ0F0.push_back( std::pair<int,float>(0,2750.) ); // outer envelope + outerZ0F0.push_back( std::pair<int,float>(0,12650.) ); // outer envelope + outerZ0F0.push_back( std::pair<int,float>(0,13400.) ); // outer envelope + outerZ0F0.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + std::vector<std::pair<int,float> > outerZ0F1; + outerZ0F1.push_back( std::pair<int,float>(0,m_outerShieldRadius) ); + outerZ0F1.push_back( std::pair<int,float>(0,2750.) ); // outer envelope + if ( m_activeAdjustLevel>0 ) { + outerZ0F1.push_back( std::pair<int,float>(0,3600.) ); + outerZ0F1.push_back( std::pair<int,float>(0,5300.) ); + outerZ0F1.push_back( std::pair<int,float>(0,7000.) ); + outerZ0F1.push_back( std::pair<int,float>(0,8500.) ); + outerZ0F1.push_back( std::pair<int,float>(0,10000.) ); + outerZ0F1.push_back( std::pair<int,float>(0,12000.) ); + } + outerZ0F1.push_back( std::pair<int,float>(0,12650.) ); // outer envelope + outerZ0F1.push_back( std::pair<int,float>(0,13400.) ); // outer envelope + outerZ0F1.push_back( std::pair<int,float>(0,aLVC.m_outerBarrelRadius) ); + + std::vector<std::vector<std::vector<std::pair<int,float> > > > outerZF(2); + outerZF[0].push_back(outerZ0F0); + outerZF[0].push_back(outerZ0F0); + outerZF[0].push_back(outerZ0F0); + outerZF[1].push_back(outerZ0F1); + outerZF[1].push_back(outerZ0F1); + outerZF[1].push_back(outerZ0F1); + + // collect everything + aLVC.m_hPartitions.push_back(barrelZF); + aLVC.m_hPartitions.push_back(swZF); + aLVC.m_hPartitions.push_back(innerZF); + aLVC.m_hPartitions.push_back(outerZF); + + return; +} + +void Muon::MuonTrackingGeometryBuilderCond::getShieldParts(LocalVariablesContainer& aLVC) const +{ + aLVC.m_shieldZPart.resize(18); + + aLVC.m_shieldZPart[0]=-21900.; // elm2 + aLVC.m_shieldZPart[1]=-21500.; // elm1 + aLVC.m_shieldZPart[2]=-21000.; // octogon + aLVC.m_shieldZPart[3]=-18000.; // tube + aLVC.m_shieldZPart[4]=-12882.; // ect + aLVC.m_shieldZPart[5]= -7930.; // ect + aLVC.m_shieldZPart[6]= -7914.; // cone + aLVC.m_shieldZPart[7]= -6941.; // disk + aLVC.m_shieldZPart[8]= -6783.; // + for (unsigned int i = 9; i<18 ; i++) aLVC.m_shieldZPart[i] = - aLVC.m_shieldZPart[17-i]; + + aLVC.m_shieldHPart.clear(); + + std::vector<std::pair<int,float> > outerShield; + outerShield.push_back(std::pair<int,float>(0,m_beamPipeRadius)); + outerShield.push_back(std::pair<int,float>(0,279.)); // outer envelope + outerShield.push_back(std::pair<int,float>(0,436.7)); // outer envelope + outerShield.push_back(std::pair<int,float>(0,1050.)); // outer envelope + outerShield.push_back(std::pair<int,float>(0,m_outerShieldRadius)); + aLVC.m_shieldHPart.push_back(outerShield); + + std::vector<std::pair<int,float> > innerShield; + innerShield.push_back(std::pair<int,float>(0,m_beamPipeRadius)); + innerShield.push_back(std::pair<int,float>(0,530.)); + innerShield.push_back(std::pair<int,float>(0,m_innerShieldRadius)); + aLVC.m_shieldHPart.push_back(innerShield); + + std::vector<std::pair<int,float> > diskShield; + diskShield.push_back(std::pair<int,float>(0,0.)); + diskShield.push_back(std::pair<int,float>(0,540.)); + diskShield.push_back(std::pair<int,float>(0,750.)); + diskShield.push_back(std::pair<int,float>(0,2700.)); + diskShield.push_back(std::pair<int,float>(0,4255.)); + aLVC.m_shieldHPart.push_back(diskShield); + + return; +} + +double Muon::MuonTrackingGeometryBuilderCond::calculateVolume( const Trk::Volume* envelope) const +{ + double envVol = 0.; + + if (!envelope) return 0.; + + const Trk::CylinderVolumeBounds* cyl = dynamic_cast<const Trk::CylinderVolumeBounds*> (&(envelope->volumeBounds())); + const Trk::CuboidVolumeBounds* box = dynamic_cast<const Trk::CuboidVolumeBounds*> (&(envelope->volumeBounds())); + const Trk::TrapezoidVolumeBounds* trd = dynamic_cast<const Trk::TrapezoidVolumeBounds*> (&(envelope->volumeBounds())); + const Trk::BevelledCylinderVolumeBounds* bcyl = dynamic_cast<const Trk::BevelledCylinderVolumeBounds*> (&(envelope->volumeBounds())); + const Trk::PrismVolumeBounds* prism = dynamic_cast<const Trk::PrismVolumeBounds*> (&(envelope->volumeBounds())); + const Trk::SimplePolygonBrepVolumeBounds* spb = dynamic_cast<const Trk::SimplePolygonBrepVolumeBounds*> (&(envelope->volumeBounds())); + const Trk::CombinedVolumeBounds* comb = dynamic_cast<const Trk::CombinedVolumeBounds*> (&(envelope->volumeBounds())); + const Trk::SubtractedVolumeBounds* sub = dynamic_cast<const Trk::SubtractedVolumeBounds*> (&(envelope->volumeBounds())); + + if ( cyl ) envVol = 2*cyl->halfPhiSector()*(cyl->outerRadius()*cyl->outerRadius()-cyl->innerRadius()*cyl->innerRadius())*cyl->halflengthZ(); + if ( box ) envVol = (8*box->halflengthX()*box->halflengthY()*box->halflengthZ()); + if ( trd ) envVol = (4*(trd->minHalflengthX()+trd->maxHalflengthX())*trd->halflengthY()*trd->halflengthZ()); + if ( bcyl ) { + int type = bcyl->type(); + if ( type<1 ) envVol = 2*bcyl->halfPhiSector()*(bcyl->outerRadius()*bcyl->outerRadius()-bcyl->innerRadius()*bcyl->innerRadius())*bcyl->halflengthZ(); + if ( type==1 ) envVol = 2*bcyl->halflengthZ()*( bcyl->halfPhiSector()*bcyl->outerRadius()*bcyl->outerRadius() + -bcyl->innerRadius()*bcyl->innerRadius()*tan(bcyl->halfPhiSector()) ); + if ( type==2 ) envVol = 2*bcyl->halflengthZ()*( -bcyl->halfPhiSector()*bcyl->innerRadius()*bcyl->innerRadius() + +bcyl->outerRadius()*bcyl->outerRadius()*tan(bcyl->halfPhiSector()) ); + if ( type==3 ) envVol = 2*bcyl->halflengthZ()*tan(bcyl->halfPhiSector())*( bcyl->outerRadius()*bcyl->outerRadius() + -bcyl->innerRadius()*bcyl->innerRadius()); + } + if ( prism ) { +#ifdef TRKDETDESCR_USEFLOATPRECISON +#define double float +#endif + std::vector<std::pair<double,double> > v=prism->xyVertices(); +#ifdef TRKDETDESCR_USEFLOATPRECISON +#undef double +#endif + double a2 = v[1].first*v[1].first+v[1].second*v[1].second + +v[0].first*v[0].first+v[0].second*v[0].second + -2*(v[0].first*v[1].first+v[0].second*v[1].second); + double c2 = v[2].first*v[2].first+v[2].second*v[2].second + +v[0].first*v[0].first+v[0].second*v[0].second + -2*(v[0].first*v[2].first+v[0].second*v[2].second); + double ca = v[1].first*v[2].first+v[1].second*v[2].second + +v[0].first*v[0].first+v[0].second*v[0].second + -v[0].first*v[1].first-v[0].second*v[1].second + -v[0].first*v[2].first-v[0].second*v[2].second; + double vv = sqrt(c2-ca*ca/a2); + envVol = vv*sqrt(a2)*prism->halflengthZ(); + } + if ( spb ) { + envVol = calculateVolume(spb->combinedVolume()); // exceptional use of combined volume (no intersections) + } + if ( comb ) { + envVol = calculateVolume(comb->first()) + calculateVolume(comb->second()); + } + if ( sub ) { + return -1; + } + + return envVol; +} + +void Muon::MuonTrackingGeometryBuilderCond::blendMaterial(LocalVariablesContainer& aLVC) const +{ + // loop over map + //std::map<const Trk::DetachedTrackingVolume*,std::vector<const Trk::TrackingVolume*>* >::iterator mIter = m_blendMap.begin(); + std::vector<const Trk::DetachedTrackingVolume*>::iterator viter = aLVC.m_blendVols.begin(); + + const std::vector<std::pair<const Trk::Volume*,float> >* cs = 0; + + // for ( ; mIter!= m_blendMap.end(); mIter++) { + // cs = (*mIter).first->constituents(); + for (;viter!= aLVC.m_blendVols.end();++viter) { + cs = (*viter)->constituents(); + if (!cs) continue; + // find material source + //const Trk::Material* detMat = (*mIter).first->trackingVolume(); + const Trk::Material* detMat = (*viter)->trackingVolume(); + //if ( (*mIter).first->trackingVolume()->confinedDenseVolumes()) detMat = (*(*mIter).first->trackingVolume()->confinedDenseVolumes())[0]; + if ( (*viter)->trackingVolume()->confinedDenseVolumes()) detMat = (*(*viter)->trackingVolume()->confinedDenseVolumes())[0]; + for (unsigned int ic=0; ic<cs->size(); ic++) { + //const Trk::Volume* nCs = new Trk::Volume(*((*cs)[ic].first),(*mIter).first->trackingVolume()->transform()); + const Trk::Volume* nCs = new Trk::Volume(*((*cs)[ic].first),(*viter)->trackingVolume()->transform()); + double fraction = (*cs)[ic].second; + double csVol = fraction*calculateVolume(nCs); + const Muon::Span* s = findVolumeSpan(&(nCs->volumeBounds()), nCs->transform(), 0.,0.,aLVC) ; + if (s) { + ATH_MSG_VERBOSE("constituent:"<<ic<<":z:"<< (*s)[0]<<","<<(*s)[1]<<":r:"<< (*s)[4]<<","<<(*s)[5] + <<":phi:"<<(*s)[2]<<","<<(*s)[3]); + double enVol = 0.; + // loop over frame volumes, check if confined + //std::vector<const Trk::TrackingVolume*>::iterator fIter = (*mIter).second->begin(); + std::vector<const Trk::TrackingVolume*>* vv =aLVC.m_blendMap[*viter]; + std::vector<const Trk::TrackingVolume*>::iterator fIter=vv->begin(); + std::vector<bool> fEncl; + fEncl.clear(); + // blending factors can be saved, and not recalculated for each clone + //for ( ; fIter!=(*mIter).second->end(); fIter++) { + for ( ; fIter!=vv->end(); fIter++) { + fEncl.push_back(enclosed(*fIter,s,aLVC)); + if ( fEncl.back() ) enVol += calculateVolume(*fIter); + } + // diluting factor + double dil = enVol>0. ? csVol/enVol : 0.; + //std::cout << "const:dil:"<< ic<<","<<dil<< std::endl; + if (dil>0.) { + //for ( fIter=(*mIter).second->begin(); fIter!=(*mIter).second->end(); fIter++) { + for ( fIter=vv->begin(); fIter!=vv->end(); fIter++) { + //if (fEncl[fIter-(*mIter).second->begin()]) { (*fIter)->addMaterial(*detMat,dil); if (m_colorCode==0) (*fIter)->registerColorCode(12) ; + if (fEncl[fIter-vv->begin()]) { (*fIter)->addMaterial(*detMat,dil); if (m_colorCode==0) (*fIter)->registerColorCode(12) ; + //ATH_MSG_VERBOSE((*fIter)->volumeName()<<" acquires material from "<< (*mIter).first->name()); } + ATH_MSG_VERBOSE((*fIter)->volumeName()<<" acquires material from "<< (*viter)->name()); } + } + ATH_MSG_VERBOSE("diluting factor:"<< dil<<" for "<< (*viter)->name()<<","<<ic); + } else { + ATH_MSG_VERBOSE("diluting factor:"<< dil<<" for "<< (*viter)->name()<<","<<ic); + } + } + delete nCs; delete s; + } + if ( m_removeBlended ) { ATH_MSG_VERBOSE("deleting "<< (*viter)->name()); delete *viter; } + } +} diff --git a/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/src/components/MuonTrackingGeometry_entries.cxx b/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/src/components/MuonTrackingGeometry_entries.cxx index 923aa7eaa8e..576b652ff9d 100644 --- a/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/src/components/MuonTrackingGeometry_entries.cxx +++ b/MuonSpectrometer/MuonDetDescr/MuonTrackingGeometry/src/components/MuonTrackingGeometry_entries.cxx @@ -3,6 +3,7 @@ #include "MuonTrackingGeometry/MuonStationTypeBuilder.h" #include "MuonTrackingGeometry/MuonInertMaterialBuilder.h" +#include "MuonTrackingGeometry/MuonTrackingGeometryBuilderCond.h" using namespace Muon; @@ -11,3 +12,4 @@ DECLARE_COMPONENT( MuonStationBuilder ) DECLARE_COMPONENT( MuonStationTypeBuilder ) DECLARE_COMPONENT( MuonInertMaterialBuilder ) +DECLARE_COMPONENT( MuonTrackingGeometryBuilderCond ) diff --git a/Simulation/ISF/ISF_Fatras/ISF_FatrasDetDescrTools/ISF_FatrasDetDescrTools/LayerMaterialProvider.h b/Simulation/ISF/ISF_Fatras/ISF_FatrasDetDescrTools/ISF_FatrasDetDescrTools/LayerMaterialProvider.h index e02deeea842..d85ca20ef79 100644 --- a/Simulation/ISF/ISF_Fatras/ISF_FatrasDetDescrTools/ISF_FatrasDetDescrTools/LayerMaterialProvider.h +++ b/Simulation/ISF/ISF_Fatras/ISF_FatrasDetDescrTools/ISF_FatrasDetDescrTools/LayerMaterialProvider.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -46,20 +46,20 @@ namespace iFatras { virtual ~LayerMaterialProvider(); /** Processor Action to work on TrackingGeometry& tgeo */ - virtual StatusCode process(const Trk::TrackingGeometry& tgeo); + virtual StatusCode process(const Trk::TrackingGeometry& tgeo) const; /** Processor Action to work on TrackingVolumes - the level is for the hierachy tree*/ - virtual StatusCode process(const Trk::TrackingVolume& tvol, size_t level = 0); + virtual StatusCode process(const Trk::TrackingVolume& tvol, size_t level = 0) const; /** Processor Action to work on Layers */ - virtual StatusCode process(const Trk::Layer& lay, size_t level = 0); + virtual StatusCode process(const Trk::Layer& lay, size_t level = 0) const; /** Processor Action to work on Surfaces */ - virtual StatusCode process(const Trk::Surface& surf, size_t level = 0); + virtual StatusCode process(const Trk::Surface& surf, size_t level = 0) const; private: - StatusCode loadMaterialMap(); //!< reatrieve the Material map from the detector store + StatusCode loadMaterialMap() const; //!< retrieve the Material map from the detector store //!< boolean switch for assignLayerMaterial mutable const Trk::LayerMaterialMap* m_layerMaterialMap; diff --git a/Simulation/ISF/ISF_Fatras/ISF_FatrasDetDescrTools/src/LayerMaterialProvider.cxx b/Simulation/ISF/ISF_Fatras/ISF_FatrasDetDescrTools/src/LayerMaterialProvider.cxx index 6ba568e5eaf..1c4d75f1a78 100644 --- a/Simulation/ISF/ISF_Fatras/ISF_FatrasDetDescrTools/src/LayerMaterialProvider.cxx +++ b/Simulation/ISF/ISF_Fatras/ISF_FatrasDetDescrTools/src/LayerMaterialProvider.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -34,7 +34,7 @@ iFatras::LayerMaterialProvider::~LayerMaterialProvider() // Processor Action to work on TrackingGeometry -StatusCode iFatras::LayerMaterialProvider::process(const Trk::TrackingGeometry& tgeo) { +StatusCode iFatras::LayerMaterialProvider::process(const Trk::TrackingGeometry& tgeo) const{ ATH_MSG_VERBOSE("Start processing the TrackingGeometry recursively"); // retrieve the highest tracking volume @@ -79,7 +79,7 @@ StatusCode iFatras::LayerMaterialProvider::process(const Trk::TrackingGeometry& } // Processor Action to work on TrackingVolumes -StatusCode iFatras::LayerMaterialProvider::process(const Trk::TrackingVolume& tvol, size_t level) { +StatusCode iFatras::LayerMaterialProvider::process(const Trk::TrackingVolume& tvol, size_t level) const{ // load the material map if not done yet if (!m_layerMaterialMap){ @@ -149,7 +149,7 @@ StatusCode iFatras::LayerMaterialProvider::process(const Trk::TrackingVolume& tv } // Processor Action to work on Layers -StatusCode iFatras::LayerMaterialProvider::process(const Trk::Layer& lay, size_t level) { +StatusCode iFatras::LayerMaterialProvider::process(const Trk::Layer& lay, size_t level) const { // load the material map if not done yet if (!m_layerMaterialMap){ @@ -187,12 +187,12 @@ StatusCode iFatras::LayerMaterialProvider::process(const Trk::Layer& lay, size_t } // Processor Action to work on Surfaces -StatusCode iFatras::LayerMaterialProvider::process(const Trk::Surface&, size_t) { +StatusCode iFatras::LayerMaterialProvider::process(const Trk::Surface&, size_t) const { return StatusCode::SUCCESS; } // load the material map from StoreGate -StatusCode iFatras::LayerMaterialProvider::loadMaterialMap() { +StatusCode iFatras::LayerMaterialProvider::loadMaterialMap() const { // ------------------------------------------------------------------------------- if (detStore()->retrieve(m_layerMaterialMap, m_layerMaterialMapName).isFailure()){ diff --git a/Tracking/TrkConditions/TrackingGeometryCondAlg/CMakeLists.txt b/Tracking/TrkConditions/TrackingGeometryCondAlg/CMakeLists.txt new file mode 100644 index 00000000000..fcae79acc82 --- /dev/null +++ b/Tracking/TrkConditions/TrackingGeometryCondAlg/CMakeLists.txt @@ -0,0 +1,40 @@ +################################################################################ +# Package: TrackingGeometryCondAlg +################################################################################ + +# Declare the package name: +atlas_subdir( TrackingGeometryCondAlg ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( + PUBLIC + Control/AthenaBaseComps + Control/AthenaKernel + GaudiKernel + Tracking/TrkDetDescr/TrkDetDescrInterfaces + Tracking/TrkDetDescr/TrkDetDescrUtils + Tracking/TrkDetDescr/TrkGeometry + InnerDetector/InDetDetDescr/InDetReadoutGeometry + PRIVATE + ) + +find_package( Eigen ) + +# Component(s) in the package: + +atlas_add_component( TrackingGeometryCondAlg + TrackingGeometryCondAlg/*.h src/*.cxx src/components/*.cxx + INCLUDE_DIRS ${EIGEN_INCLUDE_DIRS} + LINK_LIBRARIES ${EIGEN_LIBRARIES} + AthenaBaseComps + AthenaKernel + GaudiKernel + TrkDetDescrInterfaces + TrkDetDescrUtils + TrkGeometry + InDetReadoutGeometry + ) + +# Install files from the package: +atlas_install_python_modules( python/*.py ) + diff --git a/Tracking/TrkConditions/TrackingGeometryCondAlg/TrackingGeometryCondAlg/TrackingGeometryCondAlg.h b/Tracking/TrkConditions/TrackingGeometryCondAlg/TrackingGeometryCondAlg/TrackingGeometryCondAlg.h new file mode 100644 index 00000000000..b450935f4c7 --- /dev/null +++ b/Tracking/TrkConditions/TrackingGeometryCondAlg/TrackingGeometryCondAlg/TrackingGeometryCondAlg.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + + +#ifndef TRACKINGGEOMETRYCONDALG_H +#define TRACKINGGEOMETRYCONDALG_H + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "PersistentDataModel/AthenaAttributeList.h" +#include "StoreGate/ReadCondHandleKey.h" +#include "StoreGate/WriteCondHandleKey.h" + +#include "TrkGeometry/TrackingGeometry.h" +#include "TrkDetDescrInterfaces/IGeometryBuilderCond.h" +#include "TrkDetDescrInterfaces/IGeometryProcessor.h" +#include "InDetReadoutGeometry/SiDetectorElementCollection.h" + +#include "GaudiKernel/ICondSvc.h" +#include "GaudiKernel/ToolHandle.h" +#include "AthenaKernel/CLASS_DEF.h" + +namespace Trk{ +class TrackingGeometryCondAlg : public AthReentrantAlgorithm +{ +public: + TrackingGeometryCondAlg(const std::string& name, ISvcLocator* pSvcLocator); + virtual ~TrackingGeometryCondAlg() override = default; + + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& ctx) const override; + virtual StatusCode finalize() override {return StatusCode::SUCCESS;} + /** Make this algorithm clonable. */ + virtual bool isClonable() const override { return true; }; + +private: + + /// Output conditions object. + SG::WriteCondHandleKey<TrackingGeometry> m_trackingGeometryWriteKey{this, "TrackingGeometryWriteKey", "AlignedTrackingGeometry", "Key of output of TrackingGeometry for ID"}; + ServiceHandle<ICondSvc> m_condSvc{this, "CondSvc", "CondSvc"}; + ToolHandle<Trk::IGeometryBuilderCond> m_trackingGeometryBuilder {this, "GeometryBuilder", ""}; + ToolHandleArray<Trk::IGeometryProcessor> m_geometryProcessors ; +}; +} +#endif //TRACKINGGEOMETRYCONDALG_H diff --git a/Tracking/TrkConditions/TrackingGeometryCondAlg/python/AtlasTrackingGeometryCondAlg.py b/Tracking/TrkConditions/TrackingGeometryCondAlg/python/AtlasTrackingGeometryCondAlg.py new file mode 100644 index 00000000000..8a433eb66a8 --- /dev/null +++ b/Tracking/TrkConditions/TrackingGeometryCondAlg/python/AtlasTrackingGeometryCondAlg.py @@ -0,0 +1,180 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + +################################################################################## +# The AtlasTrackingGeometryCondAlg fragment +# +# usage: +# from TrackingGeometryCondAlg.AtlasTrackingGeometryCondAlg import ConfiguredTrackingGeometryCondAlg +# TrkGeoCondAlg = ConfiguredTrackingGeometryCondAlg('AtlasTrackingGeometryCondAlg') +# from AthenaCommon.AlgSequence import AthSequencer +# condSeq = AthSequencer("AthCondSeq") +# condSeq+= TrkGeoCondAlg +# +################################################################################## +# import the DetFlags for the setting +from AthenaCommon.DetFlags import DetFlags + +################################################################################# +# Material for the Geometry comes from COOL or local database +################################################################################# + +from TrkDetDescrSvc.TrkDetDescrJobProperties import TrkDetFlags + + +from TrackingGeometryCondAlg.TrackingGeometryCondAlgConf import Trk__TrackingGeometryCondAlg + +class ConfiguredTrackingGeometryCondAlg( Trk__TrackingGeometryCondAlg ) : + + # constructor + def __init__(self,name = 'AtlasTrackingGeometryCondAlg'): + + if TrkDetFlags.ConfigurationOutputLevel() < 3 : + print ('[ Configuration : start ] *** '+name+' ********************************') + print ('[ TrackingGeometryCondAlg ]') + + from AthenaCommon.AppMgr import ToolSvc + + ################################################################################# + # The Geometry Builder + ################################################################################# + + # the geometry builder alg tool + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__GeometryBuilderCond + AtlasGeometryBuilder = Trk__GeometryBuilderCond(name = 'AtlasGeometryBuilder') + # switch the building outputlevel on + AtlasGeometryBuilder.OutputLevel = TrkDetFlags.ConfigurationOutputLevel() + + # the envelope definition service + from AthenaCommon.CfgGetter import getPrivateTool,getPrivateToolClone,getPublicTool,getPublicToolClone,\ + getService,getServiceClone,getAlgorithm,getAlgorithmClone + AtlasEnvelopeSvc = getService('AtlasGeometry_EnvelopeDefSvc') + + # (ID) + if DetFlags.ID_on() : +# FIXME: removed to get the migration to CondAlg started +# # get hand on the ID Tracking Geometry Builder +# if TrkDetFlags.ISF_FatrasCustomGeometry() : +# if hasattr(ToolSvc, TrkDetFlags.ISF_FatrasCustomGeometryBuilderName()): +# InDetTrackingGeometryBuilder = getattr(ToolSvc, TrkDetFlags.ISF_FatrasCustomGeometryBuilderName()) +# elif TrkDetFlags.XMLFastCustomGeometry() : +# if hasattr(ToolSvc, TrkDetFlags.InDetTrackingGeometryBuilderName()): +# InDetTrackingGeometryBuilder = getattr(ToolSvc, TrkDetFlags.InDetTrackingGeometryBuilderName()) +# else: + if not TrkDetFlags.InDetStagedGeometryBuilder(): + from InDetTrackingGeometry.ConfiguredInDetTrackingGeometryBuilderCond import ConfiguredInDetTrackingGeometryBuilderCond as IDGeometryBuilder + else: + from InDetTrackingGeometry.ConfiguredStagedTrackingGeometryBuilderCond import ConfiguredStagedTrackingGeometryBuilderCond as IDGeometryBuilder + InDetTrackingGeometryBuilder = IDGeometryBuilder(name ='InDetTrackingGeometryBuilder') + + InDetTrackingGeometryBuilder.EnvelopeDefinitionSvc = AtlasEnvelopeSvc + InDetTrackingGeometryBuilder.OutputLevel = TrkDetFlags.InDetBuildingOutputLevel() + # and give it to the Geometry Builder + AtlasGeometryBuilder.InDetTrackingGeometryBuilder = InDetTrackingGeometryBuilder + # + # (Calo) + if DetFlags.Calo_on() : + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__CylinderVolumeCreator + CaloVolumeCreator = Trk__CylinderVolumeCreator("CaloVolumeCreator") + CaloVolumeCreator.OutputLevel = TrkDetFlags.CaloBuildingOutputLevel() + ToolSvc += CaloVolumeCreator + + from CaloTrackingGeometry.ConfiguredCaloTrackingGeometryBuilderCond import ConfiguredCaloTrackingGeometryBuilderCond as ConfiguredCaloGeo + CaloTrackingGeometryBuilder = ConfiguredCaloGeo(name='CaloTrackingGeometryBuilder'); + CaloTrackingGeometryBuilder.TrackingVolumeCreator = CaloVolumeCreator + CaloTrackingGeometryBuilder.EnvelopeDefinitionSvc = AtlasEnvelopeSvc + CaloTrackingGeometryBuilder.OutputLevel = TrkDetFlags.CaloBuildingOutputLevel() + CaloTrackingGeometryBuilder.GeometryName = 'Calo' + # and give it to the Geometry Builder + AtlasGeometryBuilder.CaloTrackingGeometryBuilder = CaloTrackingGeometryBuilder + + # (Muon) + if DetFlags.Muon_on() : + from MuonTrackingGeometry.ConfiguredMuonTrackingGeometryCond import MuonTrackingGeometryBuilderCond + MuonTrackingGeometryBuilderCond.EnvelopeDefinitionSvc = AtlasEnvelopeSvc + # and give it to the Geometry Builder + AtlasGeometryBuilder.MuonTrackingGeometryBuilder = MuonTrackingGeometryBuilderCond + + # processors + AtlasGeometryProcessors = [] + + # check whether the material retrieval is ment to be from COOL + if TrkDetFlags.MaterialSource() is 'COOL': + # the material provider + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__LayerMaterialProvider as LayerMaterialProvider + AtlasMaterialProvider = LayerMaterialProvider('AtlasMaterialProvider') + AtlasMaterialProvider.OutputLevel = TrkDetFlags.ConfigurationOutputLevel() + AtlasMaterialProvider.LayerMaterialMapName = TrkDetFlags.MaterialStoreGateKey() + + AtlasGeometryProcessors += [ AtlasMaterialProvider ] + + # the tag names + CoolDataBaseFolder = TrkDetFlags.MaterialStoreGateKey() + AtlasMaterialTag = TrkDetFlags.MaterialTagBase()+str(TrkDetFlags.MaterialVersion())+TrkDetFlags.MaterialSubVersion()+'_' + + if TrkDetFlags.ConfigurationOutputLevel() < 3 : + print '[ TrackingGeometryCondAlg ] Associating DB folder : ', CoolDataBaseFolder + + # we need the conditions interface + from IOVDbSvc.CondDB import conddb + # use a local database + if TrkDetFlags.MaterialDatabaseLocal(): + # specify the local database + DataBasePath = TrkDetFlags.MaterialDatabaseLocalPath() + DataBaseName = TrkDetFlags.MaterialDatabaseLocalName() + MagicTag = TrkDetFlags.MaterialMagicTag() + DataBaseConnection = '<dbConnection>sqlite://X;schema='+DataBasePath+DataBaseName+';dbname=OFLP200</dbConnection>' + conddb.blockFolder('/GLOBAL/TrackingGeo/LayerMaterialV2') + conddb.addFolderWithTag('',DataBaseConnection+CoolDataBaseFolder,AtlasMaterialTag+MagicTag,force=True) + if TrkDetFlags.ConfigurationOutputLevel() < 3 : + print '[ TrackingGeometryCondAlg ] Using Local Database: '+DataBaseConnection + # make sure that the pool files are in the catalog + elif TrkDetFlags.SLHC_Geometry() : + # set the folder to the SLHC location + CoolDataBaseFolder = '/GLOBAL/TrackingGeo/LayerMaterialITK' + ctag = AtlasMaterialTag+TrkDetFlags.MaterialMagicTag() + cfoldertag = CoolDataBaseFolder+' <tag>'+ctag+'</tag>' + conddb.addFolderSplitMC('GLOBAL',cfoldertag,cfoldertag) + else : + print '[ TrackingGeometryCondAlg ] base material tag : ', AtlasMaterialTag + cfolder = CoolDataBaseFolder +'<tag>TagInfoMajor/'+AtlasMaterialTag+'/GeoAtlas</tag>' + print '[ TrackingGeometryCondAlg ] translated to COOL: ', cfolder + # load the right folders (preparation for calo inclusion) + conddb.addFolderSplitMC('GLOBAL',cfolder,cfolder) + + elif TrkDetFlags.MaterialSource() is 'Input' : + # the material provider + from TrkDetDescrTools.TrkDetDescrToolsConf import Trk__InputLayerMaterialProvider + AtlasMaterialProvider = Trk__InputLayerMaterialProvider('AtlasMaterialProvider') + AtlasMaterialProvider.OutputLevel = TrkDetFlags.ConfigurationOutputLevel() + AtlasGeometryProcessors += [ AtlasMaterialProvider ] + + # material validation + if TrkDetFlags.MaterialValidation() : + # load the material inspector + from TrkDetDescrTestTools.TrkDetDescrTestToolsConf import Trk__LayerMaterialInspector + AtlasLayerMaterialInspector = Trk__LayerMaterialInspector('AtlasLayerMaterialInspector') + AtlasLayerMaterialInspector.OutputLevel = TrkDetFlags.ConfigurationOutputLevel() + + AtlasGeometryProcessors += [ AtlasLayerMaterialInspector ] + + # call the base class constructor : sets the tools + Trk__TrackingGeometryCondAlg.__init__(self,name,\ + GeometryBuilder = AtlasGeometryBuilder,\ + GeometryProcessors = AtlasGeometryProcessors, \ + OutputLevel = TrkDetFlags.ConfigurationOutputLevel()) + + # screen output of the configuration + if TrkDetFlags.ConfigurationOutputLevel() < 3 : + print self + print '* [ GeometryBuilder ]' + print AtlasGeometryBuilder + print '* [ Configuration : end ] ***'+name+'********************************' + +################################################################################## + +# now create the instance +#AtlasTrackingGeometryCondAlg = ConfiguredTrackingGeometryCondAlg('AtlasTrackingGeometryCondAlg') +# add it to the ServiceManager +#from AthenaCommon.AlgSequence import AthSequencer +#condSeq = AthSequencer("AthCondSeq") +#condSeq+= AtlasTrackingGeometryCondAlg diff --git a/Tracking/TrkConditions/TrackingGeometryCondAlg/python/AtlasTrackingGeometryCondAlgConfig.py b/Tracking/TrkConditions/TrackingGeometryCondAlg/python/AtlasTrackingGeometryCondAlgConfig.py new file mode 100644 index 00000000000..fe96f02eaf9 --- /dev/null +++ b/Tracking/TrkConditions/TrackingGeometryCondAlg/python/AtlasTrackingGeometryCondAlgConfig.py @@ -0,0 +1,293 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory +Trk__TrackingGeometryCondAlg=CompFactory.Trk__TrackingGeometryCondAlg +from IOVDbSvc.IOVDbSvcConfig import addFoldersSplitOnline +from SubDetectorEnvelopes.SubDetectorEnvelopesConfig import getEnvelopeDefSvc + +# This file is a placeholder - the entire way we build geometry needs to be rewritten so this is to unblock new configuration developments for the moment. +# It is based on: https://gitlab.cern.ch/atlas/athena/blob/master/Tracking/TrkDetDescr/TrkDetDescrSvc/python/AtlasTrackingGeometrySvc.py#L112 + +def _setupCondDB(flags, CoolDataBaseFolder, quiet=True): + result=ComponentAccumulator() + + # the tag names + materialTagBase = 'AtlasLayerMat_v' + version = 21 + sub_version = '' + + AtlasMaterialTag = materialTagBase+str(version)+sub_version+'_' + cfolder = CoolDataBaseFolder +'<tag>TagInfoMajor/'+AtlasMaterialTag+'/GeoAtlas</tag>' + + # if not quiet: + # print('[ TrackingGeometrySvc ] base material tag : ' + AtlasMaterialTag) + # print('[ TrackingGeometrySvc ] translated to COOL: ' + cfolder) + + # load the right folders + result.merge( addFoldersSplitOnline(flags,'GLOBAL',[cfolder],[cfolder],splitMC=True) ) + return result + +def _getInDetTrackingGeometryBuilder(name, flags,result, envelopeDefinitionSvc, namePrefix='', setLayerAssociation = True, buildTrtStrawLayers = False): + # Based on https://gitlab.cern.ch/atlas/athena/blob/master/InnerDetector/InDetDetDescr/InDetTrackingGeometry/python/ConfiguredInDetTrackingGeometryBuilder.py + # A lot of comments below are to help people understand differences from the above, in case we need to revert some simplifications I made + # i.e. this is far from complete, but is better than what was there before. + + # beampipe + InDet__BeamPipeBuilder=CompFactory.InDet__BeamPipeBuilderCond + beamPipeBuilder = InDet__BeamPipeBuilder(name=namePrefix+'BeamPipeBuilder') + + result.addPublicTool(beamPipeBuilder) + layerbuilders = [] + binnings = [] + colors = [] + + # Pixel + if flags.Detector.GeometryPixel: + InDet__SiLayerBuilder=CompFactory.InDet__SiLayerBuilderCond + PixelLayerBuilder = InDet__SiLayerBuilder(name=namePrefix+'PixelLayerBuilder') + PixelLayerBuilder.PixelCase = True + PixelLayerBuilder.Identification = 'Pixel' + PixelLayerBuilder.SiDetManagerLocation = 'Pixel' + # additional layers - handle with care ! + PixelLayerBuilder.BarrelAdditionalLayerRadii = [ 130 ] # The PST + PixelLayerBuilder.BarrelAdditionalLayerType = [ 0 ] # -- will shift volume boundary to PST + PixelLayerBuilder.EndcapAdditionalLayerPositionsZ = [ -1900. , 1900. ] # DBM + PixelLayerBuilder.EndcapAdditionalLayerType = [ 1 , 1 ] # DBM + # Pixel barrel specifications + # Since we don't have TrkDetFlags, using defaults here. + + # set the layer association + PixelLayerBuilder.SetLayerAssociation = setLayerAssociation + + # the binning type of the layers + PixelLayerBinning = 2 + # add it to tool service + result.addPublicTool(PixelLayerBuilder) + # put them to the caches + layerbuilders += [ PixelLayerBuilder ] + binnings += [ PixelLayerBinning ] + colors += [ 3 ] + + if flags.Detector.GeometrySCT: + # SCT building + InDet__SiLayerBuilder=CompFactory.InDet__SiLayerBuilderCond + SCT_LayerBuilder = InDet__SiLayerBuilder(name=namePrefix+'SCT_LayerBuilder') + SCT_LayerBuilder.PixelCase = False + SCT_LayerBuilder.Identification = 'SCT' + SCT_LayerBuilder.SiDetManagerLocation = 'SCT' + # additionall layers - handle with care ! + SCT_LayerBuilder.EndcapAdditionalLayerPositionsZ = [ -2850 , 2850 ] + SCT_LayerBuilder.EndcapAdditionalLayerType = [ 0 , 0 ] + # SCT barrel specifications - use defaults + # SCT endcap specifications - use defaults + # set the layer association + SCT_LayerBuilder.SetLayerAssociation = setLayerAssociation + # the binning type of the layer + SCT_LayerBinning = 2 + # SCT -> ToolSvc + result.addPublicTool(SCT_LayerBuilder) + + # put them to the caches + layerbuilders += [ SCT_LayerBuilder ] + binnings += [ SCT_LayerBinning ] + colors += [ 4 ] + + if flags.Detector.GeometryTRT: + InDet__TRT_LayerBuilder=CompFactory.InDet__TRT_LayerBuilderCond + TRT_LayerBuilder = InDet__TRT_LayerBuilder(name=namePrefix+'TRT_LayerBuilder') + # TRT barrel specifications - assume defaults + # SCT endcap specifications - assume defaults + + # set the binning from bi-aequidistant to arbitrary for complex TRT volumes + TRT_LayerBinning = 1 + if buildTrtStrawLayers: + TRT_LayerBinning = 2 + TRT_LayerBuilder.ModelLayersOnly = False + # TRT -> ToolSvc + result.addPublicTool(TRT_LayerBuilder) + + # put them to the caches + layerbuilders += [ TRT_LayerBuilder ] + binnings += [ TRT_LayerBinning ] + colors += [ 5 ] + + # helpers for the InDetTrackingGeometry Builder : layer array creator + Trk__LayerArrayCreator=CompFactory.Trk__LayerArrayCreator + InDetLayerArrayCreator = Trk__LayerArrayCreator(name = 'InDetLayerArrayCreator') + InDetLayerArrayCreator.EmptyLayerMode = 2 # deletes empty material layers from arrays + # add to ToolSvc + result.addPublicTool(InDetLayerArrayCreator) + + # helpers for the InDetTrackingGeometry Builder : volume array creator + Trk__TrackingVolumeArrayCreator=CompFactory.Trk__TrackingVolumeArrayCreator + InDetTrackingVolumeArrayCreator = Trk__TrackingVolumeArrayCreator(name = 'InDetTrackingVolumeArrayCreator') + # add to ToolSvc + result.addPublicTool(InDetTrackingVolumeArrayCreator) + + # helpers for the InDetTrackingGeometry Builder : tracking voluem helper for glueing + Trk__TrackingVolumeHelper=CompFactory.Trk__TrackingVolumeHelper + InDetTrackingVolumeHelper = Trk__TrackingVolumeHelper(name ='InDetTrackingVolumeHelper') + # the material bins - assume defaults + # add to ToolSvc + result.addPublicTool(InDetTrackingVolumeHelper) + + # helpers for the InDetTrackingGeometry Builder : cylinder volume creator + Trk__CylinderVolumeCreator=CompFactory.Trk__CylinderVolumeCreator + InDetCylinderVolumeCreator = Trk__CylinderVolumeCreator(name = 'InDetCylinderVolumeCreator') + # give it the layer array creator - assume defaults + # specifiy the binning, passive layers, entry layers - assume defaults + # add to ToolSvc + result.addPublicTool(InDetCylinderVolumeCreator) + + # the tracking geometry builder + InDet__RobustTrackingGeometryBuilder=CompFactory.InDet__RobustTrackingGeometryBuilderCond + return InDet__RobustTrackingGeometryBuilder(namePrefix+name, + BeamPipeBuilder = beamPipeBuilder, + LayerBuilders = layerbuilders, + LayerBinningType = binnings, + ColorCodes = colors, + EnvelopeDefinitionSvc = envelopeDefinitionSvc, + VolumeEnclosureDiscPositions = [ 3000., 3450. ], + TrackingVolumeCreator = InDetCylinderVolumeCreator, + LayerArrayCreator = InDetLayerArrayCreator) + + # FIXME - not sure what to do about the following: + # BuildBoundaryLayers = TrkDetFlags.InDetBuildMaterialBoundaries(), + # ReplaceAllJointBoundaries = TrkDetFlags.InDetBuildJointBoundaries(), + # OutputLevel = TrkDetFlags.InDetBuildingOutputLevel(), + # ExitVolumeName = TrkDetFlags.InDetContainerName(), + + # Probably they should just be dropped, but I leave this comment for the moment so reviewers can have a think as well. + + # Barrel Entry layers (in old config) etc were removed in 323990adfce581a635ae1809fd2ecc6a093a704c (!) + +# Replaces https://gitlab.cern.ch/atlas/athena/blob/master/Calorimeter/CaloTrackingGeometry/python/ConfiguredCaloTrackingGeometryBuilder.py +def _getCaloTrackingGeometryBuilder(name, flags,result, envelopeDefinitionSvc, trackingVolumeHelper, namePrefix=''): + # The following replaces LArCalorimeter/LArTrackingGeometry/python/ConfiguredLArVolumeBuilder.py + LAr__LArVolumeBuilder=CompFactory.LAr__LArVolumeBuilder + lArVolumeBuilder = LAr__LArVolumeBuilder(TrackingVolumeHelper = trackingVolumeHelper,) + result.addPublicTool(lArVolumeBuilder) + + # The following replaces TileCalorimeter/TileTrackingGeometry/python/ConfiguredTileVolumeBuilder.py + Tile__TileVolumeBuilder=CompFactory.Tile__TileVolumeBuilder + tileVolumeBuilder = Tile__TileVolumeBuilder( TrackingVolumeHelper = trackingVolumeHelper, ) + result.addPublicTool(tileVolumeBuilder) + + Calo__CaloTrackingGeometryBuilder=CompFactory.Calo__CaloTrackingGeometryBuilderCond + return Calo__CaloTrackingGeometryBuilder(namePrefix+name, LArVolumeBuilder = lArVolumeBuilder, + TileVolumeBuilder = tileVolumeBuilder, + TrackingVolumeHelper = trackingVolumeHelper, + EnvelopeDefinitionSvc = envelopeDefinitionSvc, + ) + +# Originally this function would use was TrkDetFlags.MaterialSource() and TrkDetFlags.MaterialValidation(). For new configuration, (temporarily?) pass as parameters. +# https://gitlab.cern.ch/atlas/athena/blob/master/Tracking/TrkDetDescr/TrkDetDescrSvc/python/AtlasTrackingGeometrySvc.py#L112 +def TrackingGeometryCondAlgCfg( flags , name = 'AtlasTrackingGeometryCondAlg', doMaterialValidation=False ) : + """ + Sets up the Tracking Geometry Conditions Algorithm + """ + result = ComponentAccumulator() + atlas_tracking_geometry_name = 'AtlasTrackingGeometry' + Trk__GeometryBuilder=CompFactory.Trk__GeometryBuilderCond + atlas_geometry_builder = Trk__GeometryBuilder(name = 'AtlasGeometryBuilder') + + atlas_env_def_service = getEnvelopeDefSvc() + result.addService(atlas_env_def_service) + + # Depending on the job configuration, setup the various detector builders, and add to atlas_geometry_builder + if flags.Detector.GeometryID: + # TODO Not sure how to handle TrkDetFlags, specifically ISF_FatrasCustomGeometry, XMLFastCustomGeometry, SLHC_Geometry + # So, here we only setup the default InDet geometry builder! + inDetTrackingGeometryBuilder = _getInDetTrackingGeometryBuilder(name ='InDetTrackingGeometryBuilder', flags=flags, result=result, envelopeDefinitionSvc=atlas_env_def_service) + result.addPublicTool(inDetTrackingGeometryBuilder) + + atlas_geometry_builder.InDetTrackingGeometryBuilder = inDetTrackingGeometryBuilder + + if flags.Detector.GeometryCalo: + Trk__CylinderVolumeCreator=CompFactory.Trk__CylinderVolumeCreator + caloVolumeCreator = Trk__CylinderVolumeCreator("CaloVolumeCreator") + result.addPublicTool(caloVolumeCreator) + + Trk__TrackingVolumeHelper=CompFactory.Trk__TrackingVolumeHelper + trackingVolumeHelper = Trk__TrackingVolumeHelper(name='TrackingVolumeHelper') + result.addPublicTool(trackingVolumeHelper) + + caloTrackingGeometryBuilder = _getCaloTrackingGeometryBuilder(name ='CaloTrackingGeometryBuilder', flags=flags, result=result, envelopeDefinitionSvc=atlas_env_def_service, trackingVolumeHelper=trackingVolumeHelper) + result.addPublicTool(caloTrackingGeometryBuilder) + atlas_geometry_builder.CaloTrackingGeometryBuilder = caloTrackingGeometryBuilder + + if flags.Detector.GeometryMuon: + # Copied from from MuonTrackingGeometry.ConfiguredMuonTrackingGeometry import MuonTrackingGeometryBuilder + Muon__MuonStationTypeBuilder=CompFactory.Muon__MuonStationTypeBuilder + muonStationTypeBuilder= Muon__MuonStationTypeBuilder(name = 'MuonStationTypeBuilder') + result.addPublicTool(muonStationTypeBuilder) + + Muon__MuonStationBuilder=CompFactory.Muon__MuonStationBuilder + muonStationBuilder= Muon__MuonStationBuilder(name = 'MuonStationBuilder') + muonStationBuilder.StationTypeBuilder = muonStationTypeBuilder + result.addPublicTool(muonStationBuilder) + + Muon__MuonInertMaterialBuilder=CompFactory.Muon__MuonInertMaterialBuilder + muonInertMaterialBuilder= Muon__MuonInertMaterialBuilder(name = 'MuonInertMaterialBuilder') + result.addPublicTool(muonInertMaterialBuilder) + + Muon__MuonTrackingGeometryBuilder=CompFactory.Muon__MuonTrackingGeometryBuilderCond + muonTrackingGeometryBuilder= Muon__MuonTrackingGeometryBuilder(name = 'MuonTrackingGeometryBuilder', EnvelopeDefinitionSvc=atlas_env_def_service) + result.addPublicTool(muonTrackingGeometryBuilder) + + atlas_geometry_builder.MuonTrackingGeometryBuilder = muonTrackingGeometryBuilder + + # Now set up processors + atlas_geometry_processors=[] + + if flags.TrackingGeometry.MaterialSource == 'COOL': + CoolDataBaseFolder = '/GLOBAL/TrackingGeo/LayerMaterialV2' # Was from TrkDetFlags.MaterialStoreGateKey() + # the material provider + Trk__LayerMaterialProvider=CompFactory.Trk__LayerMaterialProvider + atlasMaterialProvider = Trk__LayerMaterialProvider('AtlasMaterialProvider', LayerMaterialMapName=CoolDataBaseFolder) + atlas_geometry_processors += [ atlasMaterialProvider ] + + # Setup DBs + result.merge(_setupCondDB(flags, CoolDataBaseFolder)) + elif flags.TrackingGeometry.MaterialSource == 'Input': + Trk__InputLayerMaterialProvider=CompFactory.Trk__InputLayerMaterialProvider + atlasMaterialProvider = Trk__InputLayerMaterialProvider('AtlasMaterialProvider') + atlas_geometry_processors += [ atlasMaterialProvider ] + + if doMaterialValidation: + Trk__LayerMaterialInspector=CompFactory.Trk__LayerMaterialInspector + atlasLayerMaterialInspector = Trk__LayerMaterialInspector('AtlasLayerMaterialInspector') + atlas_geometry_processors += [ atlasLayerMaterialInspector ] + + condAlg = Trk__TrackingGeometryCondAlg( name, GeometryBuilder = atlas_geometry_builder, + TrackingGeometryWriteKey = atlas_tracking_geometry_name, + GeometryProcessors = atlas_geometry_processors, + BuildGeometryFromTagInfo = True) + result.addCondAlgo(condAlg, primary = True) + + return result + +if __name__ == '__main__': + from AthenaCommon.Configurable import Configurable + Configurable.configurableRun3Behavior=1 + from AthenaConfiguration.AllConfigFlags import ConfigFlags + from AthenaConfiguration.TestDefaults import defaultTestFiles + + ConfigFlags.Input.Files = defaultTestFiles.RAW + ConfigFlags.Detector.GeometryPixel = True + ConfigFlags.Detector.GeometrySCT = True + ConfigFlags.Detector.GeometryTRT = True + ConfigFlags.Detector.GeometryLAr = True + ConfigFlags.Detector.GeometryTile = True + ConfigFlags.Detector.GeometryMDT = True + ConfigFlags.Detector.GeometryTGC = True + ConfigFlags.Detector.GeometryCSC = True + ConfigFlags.Detector.GeometryRPC = True + ConfigFlags.lock() + + acc = TrackingGeometryCondAlgCfg(ConfigFlags ) + + f=open('TrackingGeometryCondAlgCfg.pkl','wb') + acc.store(f) + f.close() diff --git a/Tracking/TrkConditions/TrackingGeometryCondAlg/src/TrackingGeometryCondAlg.cxx b/Tracking/TrkConditions/TrackingGeometryCondAlg/src/TrackingGeometryCondAlg.cxx new file mode 100644 index 00000000000..572bfdb7c6b --- /dev/null +++ b/Tracking/TrkConditions/TrackingGeometryCondAlg/src/TrackingGeometryCondAlg.cxx @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + + +// Trk includes +#include "TrkGeometry/TrackingGeometry.h" +#include "AthenaKernel/IOVSvcDefs.h" + +#include "TrackingGeometryCondAlg/TrackingGeometryCondAlg.h" + + +Trk::TrackingGeometryCondAlg::TrackingGeometryCondAlg(const std::string& name, ISvcLocator* pSvcLocator) + : AthReentrantAlgorithm(name, pSvcLocator), + m_geometryProcessors(this) +{ + declareProperty("GeometryBuilder", m_trackingGeometryBuilder); + declareProperty("GeometryProcessors", m_geometryProcessors); +} + +StatusCode Trk::TrackingGeometryCondAlg::initialize() +{ + ATH_MSG_DEBUG("initialize " << name()); + + // Write Handle + ATH_CHECK(m_trackingGeometryWriteKey.initialize()); + // CondSvc + ATH_CHECK(m_condSvc.retrieve()); + // Register write handle + ATH_CHECK(m_condSvc->regHandle(this, m_trackingGeometryWriteKey)); + // Retrieve tools + ATH_CHECK(m_trackingGeometryBuilder.retrieve()); + if (m_geometryProcessors.retrieve().isFailure()){ + ATH_MSG_FATAL( "Could not retrieve " << m_geometryProcessors ); + return StatusCode::FAILURE; + } + + return StatusCode::SUCCESS; +} + +StatusCode Trk::TrackingGeometryCondAlg::execute(const EventContext& ctx) const{ + //Set up write handle + SG::WriteCondHandle<Trk::TrackingGeometry> writeHandle{m_trackingGeometryWriteKey, ctx}; + + + if (writeHandle.isValid()) { + ATH_MSG_DEBUG("Found valid write handle"); + return StatusCode::SUCCESS; + } + + //Create dummy IOV range covering 0 - inf + EventIDRange range; + + std::pair<EventIDRange, const Trk::TrackingGeometry*> trackingGeometryPair = m_trackingGeometryBuilder->trackingGeometry(ctx, std::pair<EventIDRange, const Trk::TrackingVolume*>(range, nullptr)); + // cast constness away for StoreGate + Trk::TrackingGeometry* trackingGeometry = const_cast<Trk::TrackingGeometry*>(trackingGeometryPair.second); + + // loop over the recursive geometry processors + auto gpIter = m_geometryProcessors.begin(); + auto gpIterE = m_geometryProcessors.end(); + for ( ; gpIter != gpIterE; ++ gpIter ){ + if ( (*gpIter)->process(*trackingGeometry).isFailure() ){ + ATH_MSG_FATAL("Processing of TrackingGeometry did not succeed. Abort." ); + return StatusCode::FAILURE; + } else { + ATH_MSG_VERBOSE("Successfully processed the TrackingGeometry with " << (*gpIter) ); + } + } + ATH_CHECK(writeHandle.record(trackingGeometryPair.first,trackingGeometry)); + return StatusCode::SUCCESS; +} diff --git a/Tracking/TrkConditions/TrackingGeometryCondAlg/src/components/TrackingGeometryCondAlg_entries.cxx b/Tracking/TrkConditions/TrackingGeometryCondAlg/src/components/TrackingGeometryCondAlg_entries.cxx new file mode 100644 index 00000000000..cf3e2c0fb66 --- /dev/null +++ b/Tracking/TrkConditions/TrackingGeometryCondAlg/src/components/TrackingGeometryCondAlg_entries.cxx @@ -0,0 +1,3 @@ +#include "TrackingGeometryCondAlg/TrackingGeometryCondAlg.h" + +DECLARE_COMPONENT( Trk::TrackingGeometryCondAlg ) diff --git a/Tracking/TrkConditions/TrkCondTest/CMakeLists.txt b/Tracking/TrkConditions/TrkCondTest/CMakeLists.txt new file mode 100644 index 00000000000..7540c13fa3d --- /dev/null +++ b/Tracking/TrkConditions/TrkCondTest/CMakeLists.txt @@ -0,0 +1,40 @@ +################################################################################ +# Package: TrkCondTest +################################################################################ + +# Declare the package name: +atlas_subdir( TrkCondTest ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( + PUBLIC + Control/AthenaBaseComps + Control/AthenaKernel + GaudiKernel + Tracking/TrkDetDescr/TrkDetDescrInterfaces + Tracking/TrkDetDescr/TrkDetDescrUtils + Tracking/TrkDetDescr/TrkGeometry + InnerDetector/InDetDetDescr/InDetReadoutGeometry + PRIVATE + ) + +find_package( Eigen ) + +# Component(s) in the package: + +atlas_add_component( TrackingGeometryCondAlgTest + TrkCondTest/*.h src/*.cxx src/components/*.cxx + INCLUDE_DIRS ${EIGEN_INCLUDE_DIRS} + LINK_LIBRARIES ${EIGEN_LIBRARIES} + AthenaBaseComps + AthenaKernel + GaudiKernel + TrkDetDescrInterfaces + TrkDetDescrUtils + TrkGeometry + InDetReadoutGeometry + ) + +# Install files from the package: +atlas_install_python_modules( python/*.py ) +atlas_install_joboptions( share/*.py ) diff --git a/Tracking/TrkConditions/TrkCondTest/TrkCondTest/TrackingGeometryCondAlgTest.h b/Tracking/TrkConditions/TrkCondTest/TrkCondTest/TrackingGeometryCondAlgTest.h new file mode 100644 index 00000000000..8f3c5a1b562 --- /dev/null +++ b/Tracking/TrkConditions/TrkCondTest/TrkCondTest/TrackingGeometryCondAlgTest.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TRACKINGGEOMETRYCONDALG_H +#define TRACKINGGEOMETRYCONDALG_H + +#include "AthenaBaseComps/AthAlgorithm.h" +#include "AthenaBaseComps/AthReentrantAlgorithm.h" +#include "PersistentDataModel/AthenaAttributeList.h" +#include "StoreGate/ReadCondHandleKey.h" +#include "StoreGate/WriteCondHandleKey.h" + +#include "TrkGeometry/TrackingGeometry.h" +#include "TrkDetDescrInterfaces/IGeometryBuilder.h" +#include "TrkDetDescrInterfaces/IGeometryProcessor.h" +#include "InDetReadoutGeometry/SiDetectorElementCollection.h" + +#include "GaudiKernel/ToolHandle.h" +#include "AthenaKernel/CLASS_DEF.h" + +namespace Trk{ +class TrackingGeometryCondAlgTest : public AthReentrantAlgorithm +{ +public: + TrackingGeometryCondAlgTest(const std::string& name, ISvcLocator* pSvcLocator); + virtual ~TrackingGeometryCondAlgTest() override = default; + + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& ctx)const override; + virtual StatusCode finalize() override {return StatusCode::SUCCESS;} + +private: + + /// Input conditions object. + SG::ReadCondHandleKey<TrackingGeometry> m_trackingGeometryReadKey{this, "TrackingGeometryReadKey", "AlignedTrackingGeometry", "Key of input TrackingGeometry"}; + mutable std::vector<Amg::Vector3D> m_worldVolumeCenterCollection; +}; +} +#endif //TRACKINGGEOMETRYCONDALG_H diff --git a/Tracking/TrkConditions/TrkCondTest/share/TrackingGeometryTest_jobOptions.py b/Tracking/TrkConditions/TrkCondTest/share/TrackingGeometryTest_jobOptions.py new file mode 100644 index 00000000000..7ac5625c865 --- /dev/null +++ b/Tracking/TrkConditions/TrkCondTest/share/TrackingGeometryTest_jobOptions.py @@ -0,0 +1,105 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +############################################################### +# +# Job options +# +#============================================================== + +#-------------------------------------------------------------- +# ATLAS default Application Configuration options +#-------------------------------------------------------------- + +# Use McEventSelector so we can run with AthenaMP + +#-------------------------------------------------------------- +# Private Application Configuration options +#-------------------------------------------------------------- + +from AthenaCommon.AthenaCommonFlags import athenaCommonFlags +athenaCommonFlags.FilesInput = ["/afs/cern.ch/work/r/rlangenb/public/data18_13TeV.00363979.physics_Main.daq.ESD/100evts10lumiblocks.ESD.root"] + +import AthenaPoolCnvSvc.ReadAthenaPool + +# build GeoModel +import AthenaPython.ConfigLib as apcl +cfg = apcl.AutoCfg(name = 'TrackingGeometryTest', input_files=athenaCommonFlags.FilesInput()) + +cfg.configure_job() + +from AthenaCommon.GlobalFlags import globalflags +if len(globalflags.ConditionsTag())!=0: + from IOVDbSvc.CondDB import conddb + conddb.setGlobalTag(globalflags.ConditionsTag()) +from AtlasGeoModel.InDetGMJobProperties import InDetGeometryFlags +InDetGeometryFlags.useDynamicAlignFolders=True + +import MagFieldServices.SetupField + +# the global detflags +from AthenaCommon.DetFlags import DetFlags +DetFlags.ID_setOn() +DetFlags.Calo_setOn() +DetFlags.Muon_setOn() +DetFlags.TRT_setOn() + +# Full job is a list of algorithms +from AthenaCommon.AlgSequence import AlgSequence +job = AlgSequence() + +from AtlasGeoModel import SetGeometryVersion +from AtlasGeoModel import GeoModelInit + +# switch the material loading off +from TrkDetDescrSvc.TrkDetDescrJobProperties import TrkDetFlags +TrkDetFlags.MaterialSource = 'None' +TrkDetFlags.MaterialVersion = 16 +TrkDetFlags.ConfigurationOutputLevel = VERBOSE + + +TrkDetFlags.PixelBuildingOutputLevel = VERBOSE +TrkDetFlags.SCT_BuildingOutputLevel = VERBOSE +TrkDetFlags.TRT_BuildingOutputLevel = VERBOSE +TrkDetFlags.InDetBuildingOutputLevel = VERBOSE +TrkDetFlags.ConfigurationOutputLevel = VERBOSE + + +# load the tracking geometry cond alg +from TrackingGeometryCondAlg.AtlasTrackingGeometryCondAlg import ConfiguredTrackingGeometryCondAlg +TrkGeoCondAlg = ConfiguredTrackingGeometryCondAlg('AtlasTrackingGeometryCondAlg') +from AthenaCommon.AlgSequence import AthSequencer +condSeq = AthSequencer("AthCondSeq") +condSeq+= TrkGeoCondAlg + +from TrkCondTest.TrackingGeometryCondAlgTestConf import Trk__TrackingGeometryCondAlgTest +TrkGeomCondAlgTest = Trk__TrackingGeometryCondAlgTest(name = "TrkGeomTest") +job += TrkGeomCondAlgTest + +#-------------------------------------------------------------- +# Set output level threshold (DEBUG, INFO, WARNING, ERROR, FATAL) +#-------------------------------------------------------------- + +# Output level for HelloAlg only (note name: instance, not type) +#TrackingGeometryTest = INFO + +# You can set the global output level on the message svc (not +# recommended) or by using the -l athena CLI parameter + +#-------------------------------------------------------------- +# Event related parameters +#-------------------------------------------------------------- + +theApp.EvtMax = 22 + +from AthenaCommon.AppMgr import ServiceMgr +# output level +ServiceMgr.MessageSvc.OutputLevel = INFO +# increase the number of letter reserved to the alg/tool name from 18 to 30 +ServiceMgr.MessageSvc.Format = "% F%50W%S%7W%R%T %0W%M" +# to change the default limit on number of message +ServiceMgr.MessageSvc.defaultLimit = 9999999 # all messages + +#============================================================== +# +# End of job options file +# +############################################################### diff --git a/Tracking/TrkConditions/TrkCondTest/src/TrackingGeometryCondAlgTest.cxx b/Tracking/TrkConditions/TrkCondTest/src/TrackingGeometryCondAlgTest.cxx new file mode 100644 index 00000000000..364faa70720 --- /dev/null +++ b/Tracking/TrkConditions/TrkCondTest/src/TrackingGeometryCondAlgTest.cxx @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +// Trk includes +#include "AthenaKernel/IOVSvcDefs.h" + +#include "TrkCondTest/TrackingGeometryCondAlgTest.h" + + +Trk::TrackingGeometryCondAlgTest::TrackingGeometryCondAlgTest(const std::string& name, ISvcLocator* pSvcLocator) + : AthReentrantAlgorithm(name, pSvcLocator) +{ +} + +StatusCode Trk::TrackingGeometryCondAlgTest::initialize() +{ + ATH_MSG_DEBUG("initialize " << name()); + + // Read Handle Key + ATH_CHECK(m_trackingGeometryReadKey.initialize()); + + return StatusCode::SUCCESS; +} + +StatusCode Trk::TrackingGeometryCondAlgTest::execute(const EventContext& ctx) const { + + //Set up read handle + SG::ReadCondHandle<Trk::TrackingGeometry> readHandle{m_trackingGeometryReadKey, ctx}; + if (!readHandle.isValid() || *readHandle == nullptr) { + ATH_MSG_WARNING(m_trackingGeometryReadKey.fullKey() << " is not available."); + return StatusCode::FAILURE; + } + const Trk::TrackingGeometry* trkGeom = *readHandle; + ATH_MSG_INFO( "eventID: " << ctx.eventID()); + + Amg::Vector3D center = trkGeom->highestTrackingVolume()->center(); + ATH_MSG_INFO("Center coordinates of highest tracking volume"); + ATH_MSG_INFO(center); + if(m_worldVolumeCenterCollection.size()>=1 && m_worldVolumeCenterCollection.back() != center){ + ATH_MSG_INFO("hooray, we have moved the world"); + } + m_worldVolumeCenterCollection.push_back(center); + + ATH_MSG_INFO("TrackingGeometry retrieved"); + return StatusCode::SUCCESS; +} diff --git a/Tracking/TrkConditions/TrkCondTest/src/components/TrkCondTest_entries.cxx b/Tracking/TrkConditions/TrkCondTest/src/components/TrkCondTest_entries.cxx new file mode 100644 index 00000000000..9d545d52446 --- /dev/null +++ b/Tracking/TrkConditions/TrkCondTest/src/components/TrkCondTest_entries.cxx @@ -0,0 +1,3 @@ +#include "TrkCondTest/TrackingGeometryCondAlgTest.h" + +DECLARE_COMPONENT( Trk::TrackingGeometryCondAlgTest ) diff --git a/Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/IGeometryBuilderCond.h b/Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/IGeometryBuilderCond.h new file mode 100755 index 00000000000..c0a3e1f20b2 --- /dev/null +++ b/Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/IGeometryBuilderCond.h @@ -0,0 +1,69 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// IGeometryBuilderCond.hm (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef TRKDETDESCRINTERFACES_IGEOMETRYBUILDERCOND_H +#define TRKDETDESCRINTERFACES_IGEOMETRYBUILDERCOND_H + +// Gaudi +#include "GaudiKernel/IAlgTool.h" +#include "GaudiKernel/EventContext.h" +// Trk - enum +#include "TrkDetDescrUtils/GeometrySignature.h" +// STL +#include <vector> + +class EventIDRange; +namespace Trk { + + class TrackingGeometry; + class TrackingVolume; + + /** Interface ID for IGeometryBuilderConds*/ + static const InterfaceID IID_IGeometryBuilderCond("IGeometryBuilderCond", 1, 0); + + /** @class IGeometryBuilderCond + + Interface class IGeometryBuilderCond, + the GeometryBuilder inherits from this one. + + VolumeBounds can be given optionally to force a specific size/shape/boundary + + This interface class implements protected glue and surface + exchange methods, that require friend rights to the classes + + @author Andreas.Salzburger@cern.ch + */ + class IGeometryBuilderCond : virtual public IAlgTool { + + public: + /**Virtual destructor*/ + virtual ~IGeometryBuilderCond(){} + + /** AlgTool and IAlgTool interface methods */ + static const InterfaceID& interfaceID() { return IID_IGeometryBuilderCond; } + + /** TrackingGeometry Interface methode - + * - Event context + * - pair with EventIDRange and corresponding TrackingVolume, from which + * we retrieve the volume to wrap the TrackingGeometry around. If + * TrackingGeometry is nullptr, range should be infinite (so + * intersecting with another range has no effect) + */ + virtual std::pair<EventIDRange, const TrackingGeometry*> trackingGeometry(const EventContext& ctx, std::pair<EventIDRange, const Trk::TrackingVolume*> tVolPair) const = 0; + + /** The unique signature */ + virtual GeometrySignature geometrySignature() const = 0; + + }; + +} // end of namespace + + +#endif // TRKDETDESCRINTERFACES_IGEOMETRYBUILDERCOND_H + + diff --git a/Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/IGeometryProcessor.h b/Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/IGeometryProcessor.h index 2e79fed6792..01b6bd5d76f 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/IGeometryProcessor.h +++ b/Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/IGeometryProcessor.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -40,16 +40,16 @@ namespace Trk { static const InterfaceID& interfaceID() { return IID_IGeometryProcessor; } /** Processor Action to work on TrackingGeometry& tgeo */ - virtual StatusCode process(const TrackingGeometry& tvol) = 0; + virtual StatusCode process(const TrackingGeometry& tvol) const = 0; /** Processor Action to work on TrackingVolumes - the level is for the hierachy tree*/ - virtual StatusCode process(const TrackingVolume& tvol, size_t level=0) = 0; + virtual StatusCode process(const TrackingVolume& tvol, size_t level=0) const = 0; /** Processor Action to work on Layers */ - virtual StatusCode process(const Layer& lay, size_t level=0) = 0; + virtual StatusCode process(const Layer& lay, size_t level=0) const = 0; /** Processor Action to work on Surfaces */ - virtual StatusCode process(const Surface& surf, size_t level=0) = 0; + virtual StatusCode process(const Surface& surf, size_t level=0) const = 0; }; diff --git a/Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/ILayerBuilderCond.h b/Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/ILayerBuilderCond.h new file mode 100755 index 00000000000..c929d43bdb8 --- /dev/null +++ b/Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/ILayerBuilderCond.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// ILayerBuilderCond.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef TRKDETDESCRINTERFACES_ILAYERBUILDERCOND_H +#define TRKDETDESCRINTERFACES_ILAYERBUILDERCOND_H + +// Gaudi +#include "GaudiKernel/IAlgTool.h" +#include "TrkSurfaces/Surface.h" +// STL +#include <vector> +#include <string> + +namespace Trk { + + class CylinderLayer; + class DiscLayer; + class PlaneLayer; + class Layer; + + /** Interface ID for ILayerBuilderCond*/ + static const InterfaceID IID_ILayerBuilderCond("ILayerBuilderCond", 1, 0); + + /** @class ILayerBuilderCond + Interface class ILayerBuilderConds + It inherits from IAlgTool. The actual implementation of the AlgTool depends on the SubDetector, + more detailed information should be found there. + + @author Andreas.Salzburger@cern.ch + */ + class ILayerBuilderCond : virtual public IAlgTool { + + public: + /**Virtual destructor*/ + virtual ~ILayerBuilderCond(){} + + /** AlgTool and IAlgTool interface methods */ + static const InterfaceID& interfaceID() { return IID_ILayerBuilderCond; } + + /** LayerBuilder interface method - returning Barrel-like layers */ + virtual std::pair<EventIDRange, const std::vector< const CylinderLayer* >*> cylindricalLayers(const EventContext& ctx) const = 0; + + /** LayerBuilder interface method - returning Endcap-like layers */ + virtual std::pair<EventIDRange, const std::vector< const DiscLayer* >*> discLayers(const EventContext& ctx) const = 0; + + /** LayerBuilder interface method - returning Planar-like layers */ + virtual std::pair<EventIDRange, const std::vector< const PlaneLayer* >*> planarLayers(const EventContext& ctx) const = 0; + + /** Name identification */ + virtual const std::string& identification() const = 0; + + /** Validation Action: + Can be implemented optionally, outside access to internal validation steps */ + virtual void validationAction() const {} + + protected: + /** Protected method to register the Layer to the Surface */ + void associateLayer(const Layer& lay, const Surface& sf) const { sf.associateLayer(lay); } + + }; + + +} // end of namespace + + +#endif // TRKDETDESCRINTERFACES_ILAYERBUILDERCOND_H + + diff --git a/Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/ILayerProviderCond.h b/Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/ILayerProviderCond.h new file mode 100644 index 00000000000..da5049f8b22 --- /dev/null +++ b/Tracking/TrkDetDescr/TrkDetDescrInterfaces/TrkDetDescrInterfaces/ILayerProviderCond.h @@ -0,0 +1,62 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// ILayerProviderCond.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef TRKDETDESCRINTERFACES_ILAYERPROVIDERCOND_H +#define TRKDETDESCRINTERFACES_ILAYERPROVIDERCOND_H + +// Gaudi +#include "GaudiKernel/IAlgTool.h" +#include "GaudiKernel/EventIDRange.h" +#include "GaudiKernel/EventContext.h" +// STL +#include <vector> +#include <string> + +namespace Trk { + + class Layer; + + /** Interface ID for ILayerProviderConds*/ + static const InterfaceID IID_ILayerProviderCond("ILayerProviderCond", 1, 0); + + /** @class ILayerProviderCond + + Interface class ILayerProviderConds + it feeds into the StagedGeometryBuilder + + @author Andreas.Salzburger@cern.ch + */ + class ILayerProviderCond : virtual public IAlgTool { + + public: + /**Virtual destructor*/ + virtual ~ILayerProviderCond(){} + + /** AlgTool and IAlgTool interface methods */ + static const InterfaceID& interfaceID() { return IID_ILayerProviderCond; } + + /** LayerBuilder interface method - returning the layers at negative side */ + virtual std::pair<EventIDRange, const std::vector< const Layer* > > negativeLayers(const EventContext& ctx) const = 0; + + /** LayerBuilder interface method - returning the central layers */ + virtual std::pair<EventIDRange, const std::vector< const Layer* > > centralLayers(const EventContext& ctx) const = 0; + + /** LayerBuilder interface method - returning the layers at negative side */ + virtual std::pair<EventIDRange, const std::vector< const Layer* > > positiveLayers(const EventContext& ctx) const = 0; + + /** Name identification */ + virtual const std::string& identification() const = 0; + + }; + +} // end of namespace + + +#endif // TRKDETDESCRINTERFACES_ILAYERPROVIDER_H + + diff --git a/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/GeometryAsciiDumper.h b/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/GeometryAsciiDumper.h index 831cec3dff9..1ab2e4ecd3f 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/GeometryAsciiDumper.h +++ b/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/GeometryAsciiDumper.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -52,15 +52,15 @@ namespace Trk { private: /** Current implementation: write root visualization to file stream */ - StatusCode processNode(const TrackingVolume& tvol, size_t level=0); + StatusCode processNode(const TrackingVolume& tvol, size_t level=0) const; /** Current implementation: write root visualization to file stream */ - StatusCode processNode(const Layer& lay, size_t level=0); + StatusCode processNode(const Layer& lay, size_t level=0) const; /** Current implementation: write root visualization to file stream */ - StatusCode processNode(const Surface&, size_t level=0); + StatusCode processNode(const Surface&, size_t level=0) const; - std::ofstream m_outputFile; + mutable std::ofstream m_outputFile; std::string m_outputFileName; //!< where the tree is written to int m_outputPrecision; diff --git a/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/GeometryJsonDumper.h b/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/GeometryJsonDumper.h index 9a02125c26a..5a70fc1f15c 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/GeometryJsonDumper.h +++ b/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/GeometryJsonDumper.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -52,18 +52,18 @@ namespace Trk { private: /** Current implementation: write root visualization to file stream */ - StatusCode processNode(const TrackingVolume& tvol, size_t level=0); + StatusCode processNode(const TrackingVolume& tvol, size_t level=0) const; /** Current implementation: write root visualization to file stream */ - StatusCode processNode(const Layer& lay, size_t level=0); + StatusCode processNode(const Layer& lay, size_t level=0) const; /** Current implementation: write root visualization to file stream */ - StatusCode processNode(const Surface&, size_t level=0); + StatusCode processNode(const Surface&, size_t level=0) const; - std::ofstream m_outputFile; + mutable std::ofstream m_outputFile; std::string m_outputFileName; //!< where the tree is written to int m_outputPrecision; - bool m_firstLayerWritten; + mutable bool m_firstLayerWritten; }; } diff --git a/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/GeometryTTreeDumper.h b/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/GeometryTTreeDumper.h index a7fc2e844c7..58cf1359645 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/GeometryTTreeDumper.h +++ b/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/GeometryTTreeDumper.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -45,15 +45,15 @@ namespace Trk { private: /** Current implementation: write root visualization to file stream */ - StatusCode processNode(const TrackingVolume& tvol, size_t level=0); + StatusCode processNode(const TrackingVolume& tvol, size_t level=0) const; /** Current implementation: write root visualization to file stream */ - StatusCode processNode(const Layer& lay, size_t level=0); + StatusCode processNode(const Layer& lay, size_t level=0) const; /** Current implementation: write root visualization to file stream */ - StatusCode processNode(const Surface&, size_t level=0); + StatusCode processNode(const Surface&, size_t level=0) const; - TTree* m_currentTree; //!< the tree for the currently processed tracking Volume + mutable TTree* m_currentTree; //!< the tree for the currently processed tracking Volume std::string m_treeFolder; //!< where the tree is written to }; diff --git a/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/LayerMaterialInspector.h b/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/LayerMaterialInspector.h index 4a16e07bef8..d3f5d98987b 100755 --- a/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/LayerMaterialInspector.h +++ b/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/LayerMaterialInspector.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -43,14 +43,14 @@ namespace Trk { private: /** Processor Action to work on TrackingVolumes - the level is for the hierachy tree*/ - virtual StatusCode processNode(const TrackingVolume& tvol, size_t level = 0); + virtual StatusCode processNode(const TrackingVolume& tvol, size_t level = 0) const; /** Processor Action to work on Layers */ - virtual StatusCode processNode(const Layer& lay, size_t level = 0); + virtual StatusCode processNode(const Layer& lay, size_t level = 0) const; /** Processor Action to work on Surfaces */ - virtual StatusCode processNode(const Surface& surf, size_t level = 0); - + virtual StatusCode processNode(const Surface& surf, size_t level = 0) const; + std::string m_treeFolder; }; diff --git a/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/RecursiveGeometryProcessor.h b/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/RecursiveGeometryProcessor.h index b5885f61cb7..e6b085000bc 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/RecursiveGeometryProcessor.h +++ b/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/RecursiveGeometryProcessor.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -49,28 +49,28 @@ namespace Trk { StatusCode finalize(); /** Processor Action to work on TrackingGeometry& tgeo */ - virtual StatusCode process(const TrackingGeometry& tgeo); + virtual StatusCode process(const TrackingGeometry& tgeo) const; /** Processor Action to work on TrackingVolumes - the level is for the hierachy tree*/ - virtual StatusCode process(const TrackingVolume& tvol, size_t level = 0); + virtual StatusCode process(const TrackingVolume& tvol, size_t level = 0) const; /** Processor Action to work on Layers */ - virtual StatusCode process(const Layer& lay, size_t level = 0); + virtual StatusCode process(const Layer& lay, size_t level = 0) const; /** Processor Action to work on Surfaces */ - virtual StatusCode process(const Surface& surf, size_t level = 0); + virtual StatusCode process(const Surface& surf, size_t level = 0) const; protected: /** Dedicated action for the different processors */ /** Processor Action to work on TrackingVolumes - the level is for the hierachy tree*/ - virtual StatusCode processNode(const TrackingVolume& tvol, size_t level = 0); + virtual StatusCode processNode(const TrackingVolume& tvol, size_t level = 0) const; /** Processor Action to work on Layers */ - virtual StatusCode processNode(const Layer& lay, size_t level = 0); + virtual StatusCode processNode(const Layer& lay, size_t level = 0) const; /** Processor Action to work on Surfaces */ - virtual StatusCode processNode(const Surface& surf, size_t level = 0); + virtual StatusCode processNode(const Surface& surf, size_t level = 0) const; diff --git a/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/TrackingVolumeDisplayer.h b/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/TrackingVolumeDisplayer.h index c3ff2245c76..e23b641efb4 100755 --- a/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/TrackingVolumeDisplayer.h +++ b/Tracking/TrkDetDescr/TrkDetDescrTestTools/TrkDetDescrTestTools/TrackingVolumeDisplayer.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -49,13 +49,13 @@ namespace Trk { private: /** Current implementation: write root visualization to file stream */ - StatusCode processNode(const TrackingVolume& tvol, size_t level=0); + StatusCode processNode(const TrackingVolume& tvol, size_t level=0) const; /** Current implementation: write root visualization to file stream */ - StatusCode processNode(const Layer& lay, size_t level=0); + StatusCode processNode(const Layer& lay, size_t level=0) const; /** Current implementation: write root visualization to file stream */ - StatusCode processNode(const Surface&, size_t level=0); + StatusCode processNode(const Surface&, size_t level=0) const; void openFile(std::ofstream& output, const std::string& filename) const; //!< File handling: open + write header void closeFile(std::ofstream& output) const; //!< File handling: write footer + close diff --git a/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/GeometryAsciiDumper.cxx b/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/GeometryAsciiDumper.cxx index afb550433ab..723f5a871d7 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/GeometryAsciiDumper.cxx +++ b/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/GeometryAsciiDumper.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -57,7 +57,7 @@ StatusCode Trk::GeometryAsciiDumper::finalize() -StatusCode Trk::GeometryAsciiDumper::processNode(const Trk::TrackingVolume& tvol, size_t level) +StatusCode Trk::GeometryAsciiDumper::processNode(const Trk::TrackingVolume& tvol, size_t level) const { ATH_MSG_VERBOSE("Dumping information for TrackingVolume."); @@ -95,7 +95,7 @@ StatusCode Trk::GeometryAsciiDumper::processNode(const Trk::TrackingVolume& tvol } -StatusCode Trk::GeometryAsciiDumper::processNode(const Trk::Layer& lay, size_t level) +StatusCode Trk::GeometryAsciiDumper::processNode(const Trk::Layer& lay, size_t level) const { ATH_MSG_VERBOSE("Dumping information for Layer."); @@ -121,7 +121,7 @@ StatusCode Trk::GeometryAsciiDumper::processNode(const Trk::Layer& lay, size_t l } -StatusCode Trk::GeometryAsciiDumper::processNode(const Trk::Surface& sf, size_t level) +StatusCode Trk::GeometryAsciiDumper::processNode(const Trk::Surface& sf, size_t level) const { ATH_MSG_VERBOSE("Dumping information for Surfaces."); std::stringstream levelBuffer; diff --git a/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/GeometryJsonDumper.cxx b/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/GeometryJsonDumper.cxx index 264061da392..43d78d6609e 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/GeometryJsonDumper.cxx +++ b/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/GeometryJsonDumper.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -59,13 +59,13 @@ StatusCode Trk::GeometryJsonDumper::finalize() -StatusCode Trk::GeometryJsonDumper::processNode(const Trk::TrackingVolume& /*tvol*/, size_t /*level*/) +StatusCode Trk::GeometryJsonDumper::processNode(const Trk::TrackingVolume& /*tvol*/, size_t /*level*/) const { return StatusCode::SUCCESS; } -StatusCode Trk::GeometryJsonDumper::processNode(const Trk::Layer& lay, size_t /*level*/) +StatusCode Trk::GeometryJsonDumper::processNode(const Trk::Layer& lay, size_t /*level*/) const { ATH_MSG_VERBOSE("Dumping information for Layer with index " << lay.layerIndex().value()); @@ -112,7 +112,7 @@ StatusCode Trk::GeometryJsonDumper::processNode(const Trk::Layer& lay, size_t /* } -StatusCode Trk::GeometryJsonDumper::processNode(const Trk::Surface& /*sf*/, size_t /*level*/) +StatusCode Trk::GeometryJsonDumper::processNode(const Trk::Surface& /*sf*/, size_t /*level*/) const { ATH_MSG_VERBOSE("Dumping information for Surfaces."); diff --git a/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/GeometryTTreeDumper.cxx b/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/GeometryTTreeDumper.cxx index 361f41fd997..235a3b74adb 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/GeometryTTreeDumper.cxx +++ b/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/GeometryTTreeDumper.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -33,7 +33,7 @@ Trk::GeometryTTreeDumper::~GeometryTTreeDumper() {} -StatusCode Trk::GeometryTTreeDumper::processNode(const Trk::TrackingVolume& tvol, size_t) +StatusCode Trk::GeometryTTreeDumper::processNode(const Trk::TrackingVolume& tvol, size_t) const { ATH_MSG_VERBOSE("Dumping information for TrackingVolume."); // clean up from the previous event @@ -73,7 +73,7 @@ StatusCode Trk::GeometryTTreeDumper::processNode(const Trk::TrackingVolume& tvol } -StatusCode Trk::GeometryTTreeDumper::processNode(const Trk::Layer& lay, size_t) +StatusCode Trk::GeometryTTreeDumper::processNode(const Trk::Layer& lay, size_t) const { ATH_MSG_VERBOSE("Dumping information for Layer."); @@ -90,7 +90,7 @@ StatusCode Trk::GeometryTTreeDumper::processNode(const Trk::Layer& lay, size_t) } -StatusCode Trk::GeometryTTreeDumper::processNode(const Trk::Surface& sf, size_t) +StatusCode Trk::GeometryTTreeDumper::processNode(const Trk::Surface& sf, size_t) const { ATH_MSG_VERBOSE("Dumping information for Surfaces."); diff --git a/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/LayerMaterialInspector.cxx b/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/LayerMaterialInspector.cxx index 960ee66c1b9..a3efa72db21 100755 --- a/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/LayerMaterialInspector.cxx +++ b/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/LayerMaterialInspector.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -33,12 +33,12 @@ Trk::LayerMaterialInspector::LayerMaterialInspector(const std::string& t, const Trk::LayerMaterialInspector::~LayerMaterialInspector() {} -StatusCode Trk::LayerMaterialInspector::processNode(const Trk::TrackingVolume& , size_t) +StatusCode Trk::LayerMaterialInspector::processNode(const Trk::TrackingVolume& , size_t) const { return StatusCode::SUCCESS; } -StatusCode Trk::LayerMaterialInspector::processNode(const Trk::Layer& lay, size_t) +StatusCode Trk::LayerMaterialInspector::processNode(const Trk::Layer& lay, size_t) const { const Trk::TrackingVolume* tvol = lay.enclosingTrackingVolume(); @@ -152,7 +152,7 @@ StatusCode Trk::LayerMaterialInspector::processNode(const Trk::Layer& lay, size_ return StatusCode::SUCCESS; } -StatusCode Trk::LayerMaterialInspector::processNode(const Trk::Surface& , size_t) +StatusCode Trk::LayerMaterialInspector::processNode(const Trk::Surface& , size_t) const { return StatusCode::SUCCESS; } diff --git a/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/RecursiveGeometryProcessor.cxx b/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/RecursiveGeometryProcessor.cxx index 841be93c2bb..1fe9d38a6c1 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/RecursiveGeometryProcessor.cxx +++ b/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/RecursiveGeometryProcessor.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -43,7 +43,7 @@ StatusCode Trk::RecursiveGeometryProcessor::finalize() } // Processor Action to work on TrackingGeometry -StatusCode Trk::RecursiveGeometryProcessor::process(const Trk::TrackingGeometry& tgeo) { +StatusCode Trk::RecursiveGeometryProcessor::process(const Trk::TrackingGeometry& tgeo) const { ATH_MSG_VERBOSE("Start processing the TrackingGeometry recursively"); // retrieve the highest tracking volume @@ -58,7 +58,7 @@ StatusCode Trk::RecursiveGeometryProcessor::process(const Trk::TrackingGeometry& } // Processor Action to work on TrackingVolumes -StatusCode Trk::RecursiveGeometryProcessor::process(const Trk::TrackingVolume& tvol, size_t level) { +StatusCode Trk::RecursiveGeometryProcessor::process(const Trk::TrackingVolume& tvol, size_t level) const { std::stringstream displayBuffer; for (size_t il = 0; il < level; ++il) displayBuffer << " "; @@ -121,7 +121,7 @@ StatusCode Trk::RecursiveGeometryProcessor::process(const Trk::TrackingVolume& t } // Processor Action to work on Layers -StatusCode Trk::RecursiveGeometryProcessor::process(const Trk::Layer& lay, size_t level) { +StatusCode Trk::RecursiveGeometryProcessor::process(const Trk::Layer& lay, size_t level) const { std::stringstream displayBuffer; for (size_t il = 0; il < level; ++il) displayBuffer << " "; @@ -155,20 +155,20 @@ StatusCode Trk::RecursiveGeometryProcessor::process(const Trk::Layer& lay, size_ } // Processor Action to work on Surfaces -StatusCode Trk::RecursiveGeometryProcessor::process(const Trk::Surface& surf, size_t level) { +StatusCode Trk::RecursiveGeometryProcessor::process(const Trk::Surface& surf, size_t level) const { return processNode(surf, level); } // Processor Action to work on TrackingVolume - to be overloaded -StatusCode Trk::RecursiveGeometryProcessor::processNode(const Trk::TrackingVolume&, size_t ) { +StatusCode Trk::RecursiveGeometryProcessor::processNode(const Trk::TrackingVolume&, size_t ) const { return StatusCode::SUCCESS; } // Processor Action to work on Layers - to be overloaded -StatusCode Trk::RecursiveGeometryProcessor::processNode(const Trk::Layer&, size_t ) { +StatusCode Trk::RecursiveGeometryProcessor::processNode(const Trk::Layer&, size_t ) const { return StatusCode::SUCCESS; } // Processor Action to work on Surfaces - to be overloaded -StatusCode Trk::RecursiveGeometryProcessor::processNode(const Trk::Surface&, size_t ) { +StatusCode Trk::RecursiveGeometryProcessor::processNode(const Trk::Surface&, size_t ) const { return StatusCode::SUCCESS; } diff --git a/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/TrackingVolumeDisplayer.cxx b/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/TrackingVolumeDisplayer.cxx index 6cecce2e0fa..a90f95cfec6 100755 --- a/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/TrackingVolumeDisplayer.cxx +++ b/Tracking/TrkDetDescr/TrkDetDescrTestTools/src/TrackingVolumeDisplayer.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -125,7 +125,7 @@ void Trk::TrackingVolumeDisplayer::closeFile(std::ofstream& out) const } -StatusCode Trk::TrackingVolumeDisplayer::processNode(const Trk::TrackingVolume& tvol, size_t) +StatusCode Trk::TrackingVolumeDisplayer::processNode(const Trk::TrackingVolume& tvol, size_t) const { ATH_MSG_VERBOSE("Writing display information for TrackingVolume."); @@ -163,7 +163,7 @@ StatusCode Trk::TrackingVolumeDisplayer::processNode(const Trk::TrackingVolume& } -StatusCode Trk::TrackingVolumeDisplayer::processNode(const Trk::Layer& lay, size_t) +StatusCode Trk::TrackingVolumeDisplayer::processNode(const Trk::Layer& lay, size_t) const { ATH_MSG_VERBOSE("Writing display information for Layer."); @@ -256,7 +256,7 @@ StatusCode Trk::TrackingVolumeDisplayer::processNode(const Trk::Layer& lay, size } -StatusCode Trk::TrackingVolumeDisplayer::processNode(const Trk::Surface& sf, size_t) +StatusCode Trk::TrackingVolumeDisplayer::processNode(const Trk::Surface& sf, size_t) const { ++s_displaySurfaces; diff --git a/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/GenericGeometryBuilderCond.h b/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/GenericGeometryBuilderCond.h new file mode 100644 index 00000000000..0e3e2aa1c92 --- /dev/null +++ b/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/GenericGeometryBuilderCond.h @@ -0,0 +1,83 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// GenericGeometryBuilderCond.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef TRKDETDESCRTOOLS_GENERICGEOMETRYBUILDERCOND_H +#define TRKDETDESCRTOOLS_GENERICGEOMETRYBUILDERCOND_H + +// Amg +#include "GeoPrimitives/GeoPrimitives.h" +// Trk +#include "TrkDetDescrInterfaces/IGeometryBuilderCond.h" +#include "TrkDetDescrUtils/GeometrySignature.h" + +// Gaudi & Athena +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/ToolHandle.h" + +class IEnvelopeDefSvc; + +namespace Trk { + + class TrackingGeometry; + class TrackingVolume; + class ITrackingVolumeCreator; + class ITrackingVolumeHelper; + + /** @class GenericGeometryBuilderCond + + A TrackingGeometry builder that takes the EnvelopSvc and creates + a very simple generic tracking geoemtry configured with Layers + + @author Andreas.Salzburger@cern.ch + */ + + class GenericGeometryBuilderCond : public AthAlgTool, virtual public IGeometryBuilderCond { + + public: + /** Constructor */ + GenericGeometryBuilderCond(const std::string&,const std::string&,const IInterface*); + + /** Destructor */ + virtual ~GenericGeometryBuilderCond(); + + /** AlgTool initialize method */ + StatusCode initialize(); + + /** AlgTool finalize method */ + StatusCode finalize(); + + /** TrackingGeometry Interface method - optionally a pointer to Bounds */ + std::pair<EventIDRange, const Trk::TrackingGeometry*> trackingGeometry(const EventContext& ctx, std::pair<EventIDRange, const Trk::TrackingVolume*> tVolPair) const; + + /** The unique signature */ + GeometrySignature geometrySignature() const; + + private: + ServiceHandle<IEnvelopeDefSvc> m_enclosingEnvelopeSvc; //!< The service that determines the outermost boundaries + int m_enclosingEnvelope; //!< define which service you wanna have + + ToolHandle<Trk::ITrackingVolumeCreator> m_trackingVolumeCreator; //!< Helper Tool to create TrackingVolumes + + int m_geometrySignature; //!< should hopefully correspond soon to the enclosing envelope + std::string m_geometryName; //!< name for the volumes + int m_geometryColorCode; //!< ->registerColorCode() + + double m_barrelFraction; //!< Barrel configuration + int m_barrelLayers; //!< Barrel configuration + int m_endcapLayers; //!< Endcap configuration + mutable bool m_extendedEndcap; //!< extended Endcap configuration + int m_extendedEndcapLayers; //!< extended Endcap configuration + + }; + + inline GeometrySignature GenericGeometryBuilderCond::geometrySignature() const { return (GeometrySignature)m_geometrySignature; } + +} // end of namespace + +#endif // TRKDETDESCRTOOLS_GENERICGEOMETRYBUILDERCOND_H + diff --git a/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/GeometryBuilderCond.h b/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/GeometryBuilderCond.h new file mode 100755 index 00000000000..15aea0b5cac --- /dev/null +++ b/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/GeometryBuilderCond.h @@ -0,0 +1,107 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// GeometryBuilderCond.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef TRKDETDESCRTOOLS_GEOMETRYBUILDERCOND_H +#define TRKDETDESCRTOOLS_GEOMETRYBUILDERCOND_H + +// Amg +#include "GeoPrimitives/GeoPrimitives.h" +// Trk +#include "TrkDetDescrInterfaces/IGeometryBuilderCond.h" +#include "TrkDetDescrUtils/GeometrySignature.h" +#include "TrkGeometry/TrackingVolumeManipulator.h" +#include "TrkGeometry/Material.h" +// Gaudi & Athena +#include "AthenaBaseComps/AthAlgTool.h" +#include "GaudiKernel/ToolHandle.h" + +#ifdef TRKDETDESCR_MEMUSAGE +#include "TrkDetDescrUtils/MemoryLogger.h" +#endif + +namespace Trk { + + class TrackingGeometry; + class TrackingVolume; + class ITrackingVolumeBuilder; + class ITrackingVolumeHelper; + class ITrackingVolumeArrayCreator; + + /** @class GeometryBuilderCond + + The Trk::TrackingGeometry Builder for ATLAS Geometry + + It retrieves Trk::TrackingGeometry builders for the subdetectors and joins them together + to a single Trk::TrackingGeometry. + + @author Andreas.Salzburger@cern.ch + */ + + class GeometryBuilderCond : public AthAlgTool, + public TrackingVolumeManipulator, + virtual public IGeometryBuilderCond { + + public: + /** Constructor */ + GeometryBuilderCond(const std::string&,const std::string&,const IInterface*); + + /** Destructor */ + virtual ~GeometryBuilderCond(); + + /** AlgTool initialize method */ + StatusCode initialize(); + + /** AlgTool finalize method */ + StatusCode finalize(); + + /** TrackingGeometry Interface method - optionally a pointer to Bounds */ + std::pair<EventIDRange, const Trk::TrackingGeometry*> trackingGeometry(const EventContext& ctx, std::pair<EventIDRange, const Trk::TrackingVolume*> tVolPair) const; + + /** The unique signature */ + GeometrySignature geometrySignature() const { return Trk::Global; } + + private: + + /** TrackingGeometry for ATLAS setup */ + std::pair<EventIDRange, const Trk::TrackingGeometry*> atlasTrackingGeometry(const EventContext& ctx) const; + +#ifdef TRKDETDESCR_MEMUSAGE + MemoryLogger m_memoryLogger; //!< in case the memory is logged +#endif + + bool m_createWorld; //!< Boolean Switch to create World manually + int m_navigationLevel; //!< NavigationLevel + + std::vector< double > m_worldDimension; //!< The dimensions of the manually created world + std::vector< double > m_worldMaterialProperties; //!< The material properties of the created world + Material m_worldMaterial; //!< the world material + + // -------------------------- Tools for geometry building ------------------------------------------------------ // + + ToolHandle<ITrackingVolumeArrayCreator> m_trackingVolumeArrayCreator; //!< Helper Tool to create TrackingVolume Arrays + + ToolHandle<ITrackingVolumeHelper> m_trackingVolumeHelper; //!< Helper Tool to create TrackingVolumes + + //bool m_inDetGeometry; //!< switch on TrackingGeometry for the InnerDetector + ToolHandle<IGeometryBuilderCond> m_inDetGeometryBuilderCond; //!< GeometryBuilderCond for the InnerDetector + + bool m_caloGeometry; //!< switch on TrackingGeometry for the Calorimeters + ToolHandle<IGeometryBuilderCond> m_caloGeometryBuilderCond; //!< GeometryBuilderCond for the Calorimeters + + bool m_muonGeometry; //!< GeometryBuilderCond for the Muon System + ToolHandle<IGeometryBuilderCond> m_muonGeometryBuilderCond; //!< GeometryBuilderCond for the Muon System + + bool m_compactify; //!< optimize event memory usage: register all surfaces with TG + bool m_synchronizeLayers; //!< synchronize contained layer dimensions to volumes + + }; + +} // end of namespace + +#endif // TRKDETDESCRTOOLS_GEOMETRYBUILDERCOND_H + diff --git a/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/InputLayerMaterialProvider.h b/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/InputLayerMaterialProvider.h index 55ca754bfdf..12ee4de10dd 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/InputLayerMaterialProvider.h +++ b/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/InputLayerMaterialProvider.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -45,16 +45,16 @@ namespace Trk { virtual StatusCode initialize(); /** Processor Action to work on TrackingGeometry& tgeo */ - virtual StatusCode process(const TrackingGeometry& tgeo); + virtual StatusCode process(const TrackingGeometry& tgeo) const; /** Processor Action to work on TrackingVolumes - the level is for the hierachy tree*/ - virtual StatusCode process(const TrackingVolume& tvol, size_t level = 0); + virtual StatusCode process(const TrackingVolume& tvol, size_t level = 0) const; /** Processor Action to work on Layers */ - virtual StatusCode process(const Layer& lay, size_t level = 0); + virtual StatusCode process(const Layer& lay, size_t level = 0) const; /** Processor Action to work on Surfaces */ - virtual StatusCode process(const Surface& surf, size_t level = 0); + virtual StatusCode process(const Surface& surf, size_t level = 0) const; private: bool m_constantMaterialToAllLayers; //!< just assign a dummy material to all layers diff --git a/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/LayerMaterialProvider.h b/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/LayerMaterialProvider.h index 90e1553759c..69f164d1fee 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/LayerMaterialProvider.h +++ b/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/LayerMaterialProvider.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -42,23 +42,25 @@ namespace Trk { virtual ~LayerMaterialProvider(); /** Processor Action to work on TrackingGeometry& tgeo */ - virtual StatusCode process(const TrackingGeometry& tgeo); + virtual StatusCode process(const TrackingGeometry& tgeo) const; /** Processor Action to work on TrackingVolumes - the level is for the hierachy tree*/ - virtual StatusCode process(const TrackingVolume& tvol, size_t level = 0); + virtual StatusCode process(const TrackingVolume& tvol, size_t level = 0) const; /** Processor Action to work on Layers */ - virtual StatusCode process(const Layer& lay, size_t level = 0); + virtual StatusCode process(const Layer& lay, size_t level = 0) const; /** Processor Action to work on Surfaces */ - virtual StatusCode process(const Surface& surf, size_t level = 0); + virtual StatusCode process(const Surface& surf, size_t level = 0) const; private: - StatusCode loadMaterialMap(); //!< reatrieve the Material map from the detector store + StatusCode loadMaterialMap() const; //!< reatrieve the Material map from the detector store //!< boolean switch for assignLayerMaterial - mutable const LayerMaterialMap* m_layerMaterialMap; + + mutable std::once_flag m_loadMapOnceFlag ATLAS_THREAD_SAFE; + mutable const LayerMaterialMap* m_layerMaterialMap ATLAS_THREAD_SAFE; std::string m_layerMaterialMapName; diff --git a/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/LayerProviderCond.h b/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/LayerProviderCond.h new file mode 100644 index 00000000000..95850128548 --- /dev/null +++ b/Tracking/TrkDetDescr/TrkDetDescrTools/TrkDetDescrTools/LayerProviderCond.h @@ -0,0 +1,72 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// LayerProviderCond.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef TRKDETDESCRTOOLS_LAYERPROVIDERCOND_H +#define TRKDETDESCRTOOLS_LAYERPROVIDERCOND_H + +// Trk +#include "TrkDetDescrInterfaces/ILayerProviderCond.h" +// Gaudi & Athena +#include "GaudiKernel/ToolHandle.h" +#include "AthenaBaseComps/AthAlgTool.h" + + +namespace Trk { + + class Layer; + class ILayerBuilderCond; + + + /** @class LayerProviderCond + + Wrapper around an ILayerBuilderCond to feed into the StagedGeometryBuilder + + @author Andreas.Salzburger@cern.ch + */ + + class LayerProviderCond : public AthAlgTool, virtual public ILayerProviderCond { + + public: + /** Constructor */ + LayerProviderCond(const std::string&,const std::string&,const IInterface*); + + /** Destructor */ + virtual ~LayerProviderCond(); + + /** initialize */ + StatusCode initialize(); + + /** finalize */ + StatusCode finalize(); + + /** LayerBuilder interface method - returning the layers at negative side */ + std::pair<EventIDRange, const std::vector< const Layer* > > negativeLayers(const EventContext& ctx) const; + + /** LayerBuilder interface method - returning the central layers */ + std::pair<EventIDRange, const std::vector< const Layer* > > centralLayers(const EventContext& ctx) const; + + /** LayerBuilder interface method - returning the layers at negative side */ + std::pair<EventIDRange, const std::vector< const Layer* > > positiveLayers(const EventContext& ctx) const; + + /** Name identification */ + const std::string& identification() const; + + private: + /** LayerBuilder interface method - returning the layers at negative side */ + std::pair<EventIDRange, const std::vector< const Layer* > > discLayers(const EventContext& ctx, int posneg) const; + + ToolHandle<ILayerBuilderCond> m_layerBuilder; + mutable std::vector<const Trk::Layer*> m_layerCache; + + }; + + +} // end of namespace + +#endif // TRKDETDESCRTOOLS_LAYERPROVIDERCOND_H + diff --git a/Tracking/TrkDetDescr/TrkDetDescrTools/src/GenericGeometryBuilderCond.cxx b/Tracking/TrkDetDescr/TrkDetDescrTools/src/GenericGeometryBuilderCond.cxx new file mode 100644 index 00000000000..f65cdef1ce2 --- /dev/null +++ b/Tracking/TrkDetDescr/TrkDetDescrTools/src/GenericGeometryBuilderCond.cxx @@ -0,0 +1,281 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// GenericGeometryBuilderCond.cxx, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +// EnvelopeDefinitionService +#include "SubDetectorEnvelopes/IEnvelopeDefSvc.h" +// Trk include +#include "TrkDetDescrTools/GenericGeometryBuilderCond.h" +#include "TrkDetDescrInterfaces/ITrackingVolumeCreator.h" +#include "TrkDetDescrInterfaces/ITrackingVolumeHelper.h" +#include "TrkVolumes/CylinderVolumeBounds.h" +#include "TrkGeometry/TrackingVolume.h" +#include "TrkGeometry/TrackingGeometry.h" +#include "TrkGeometry/Material.h" +// Amg +#include "GeoPrimitives/GeoPrimitives.h" +// STD +#include <map> +// Gaudi +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/SystemOfUnits.h" + + +// constructor +Trk::GenericGeometryBuilderCond::GenericGeometryBuilderCond(const std::string& t, const std::string& n, const IInterface* p) +: AthAlgTool(t,n,p), + m_enclosingEnvelopeSvc("AtlasEnvelopeDefSvc", n), + m_enclosingEnvelope(0), + m_trackingVolumeCreator(""), + m_geometrySignature(0), + m_geometryName("Undefined"), + m_geometryColorCode(8), + m_barrelFraction(0.75), + m_barrelLayers(10), + m_endcapLayers(20), + m_extendedEndcap(false), + m_extendedEndcapLayers(5) +{ + // declare the interface + declareInterface<Trk::IGeometryBuilderCond>(this); + // Tools & Services + declareProperty("EnvelopeDefinitionSvc", m_enclosingEnvelopeSvc); + declareProperty("Envelope", m_enclosingEnvelope); + declareProperty("TrackingVolumeCreator", m_trackingVolumeCreator); + // configuration + declareProperty("GeometrySignature", m_geometrySignature); + declareProperty("GeometryName", m_geometryName); + declareProperty("GeometryColorCode", m_geometryColorCode); + // Barrel Layer configuration + declareProperty("BarrelFraction", m_barrelFraction); + declareProperty("BarrelLayers", m_barrelLayers); + // Endcap Layer configuration + declareProperty("EndcapLayers", m_endcapLayers); + // Extended endcap Layer configuration + declareProperty("ExtendedEndcap", m_extendedEndcap); + declareProperty("ExtendedEndcapLayers", m_extendedEndcapLayers); +} + +// destructor +Trk::GenericGeometryBuilderCond::~GenericGeometryBuilderCond() +{} + +// Athena standard methods - initialize +StatusCode Trk::GenericGeometryBuilderCond::initialize() +{ + // Retrieve the volume array creator ---------------------------------------------------- + if (m_enclosingEnvelopeSvc.retrieve().isFailure()) { + ATH_MSG_FATAL("Failed to retrieve EnvelopeSvc " << m_enclosingEnvelopeSvc ); + return StatusCode::FAILURE; + } else + ATH_MSG_INFO( "Retrieved " << m_enclosingEnvelopeSvc ); + + // Retrieve the tracking volume creator -------------------------------------------------- + if (m_trackingVolumeCreator.retrieve().isFailure()) { + ATH_MSG_FATAL("Failed to retrieve tool " << m_trackingVolumeCreator ); + return StatusCode::FAILURE; + } else + ATH_MSG_INFO( "Retrieved tool " << m_trackingVolumeCreator ); + + ATH_MSG_INFO( " initialize() successful" ); + return StatusCode::SUCCESS; +} + +// finalize +StatusCode Trk::GenericGeometryBuilderCond::finalize() +{ + ATH_MSG_INFO( "finalize() successful." ); + return StatusCode::SUCCESS; +} + + +std::pair<EventIDRange, const Trk::TrackingGeometry*> Trk::GenericGeometryBuilderCond::trackingGeometry(const EventContext& /*ctx*/, std::pair< EventIDRange, const Trk::TrackingVolume*> innerVolPair) const +{ + + ATH_MSG_VERBOSE("Starting to build TrackingGeometry for GeometrySignature : " << m_geometrySignature ); + + // the geometry to be constructed + const Trk::TrackingGeometry* tGeometry = 0; + + double innerVolumeRadius = 0.; + double innerVolumeHalfZ = 0.; + double enclosingVolumeRadius = 0.; + double enclosingVolumeHalfZ = 0.; + double enclosingExtendedVolumeRadius = 0.; + double enclosingExtendedVolumeHalfZ = 0.; + + // vacuum + Trk::Material vacuum; + + RZPairVector envelopeDefs; + // build the inner detector if configured + if (m_geometrySignature == Trk::ID){ + // get the dimensions from the envelope service + envelopeDefs = m_enclosingEnvelopeSvc->getInDetRZValues(); + ATH_MSG_VERBOSE(" -> retrieved Inner Detector envelope definitions at size " << envelopeDefs.size()); + } else if ( m_geometrySignature == Trk::Calo ){ + // get the dimensions from the envelope service + envelopeDefs = m_enclosingEnvelopeSvc->getCaloRZValues(); + ATH_MSG_VERBOSE(" -> retrieved Calorimeter envelope definitions at size " << envelopeDefs.size()); + } else if ( m_geometrySignature == Trk::MS ) { + // get the dimensions from the envelope service + envelopeDefs = m_enclosingEnvelopeSvc->getMuonRZValues(); + ATH_MSG_VERBOSE(" -> retrieved Muon System envelope definitions at size " << envelopeDefs.size()); + } else { + ATH_MSG_WARNING("No geometry signature found, return 0."); + //dummy infinite range + EventIDRange range; + return std::make_pair(range,tGeometry); + } + + // ------------------------------- overall dimensions ---------------------------------------------- + // get the maximum extend in R + for ( auto& rzIter : envelopeDefs){ + if ( rzIter.first > enclosingVolumeRadius ) { + // maximal r-extend + enclosingVolumeRadius = rzIter.first; + enclosingVolumeHalfZ = fabs(rzIter.second); + } + } + ATH_MSG_VERBOSE(" -> Overall dimensions estimated as (r,hZ) = " << enclosingVolumeRadius << ", " << enclosingVolumeHalfZ); + + // we need to build extended barrels --------------------------------------------------------------- + if ( m_extendedEndcap && envelopeDefs.size() > 4){ + ATH_MSG_VERBOSE(" -> configured to build extended Barrel, checking for RZpair direction."); + // find out the direction of the rz points point + Amg::Vector3D p1(envelopeDefs[0].second,envelopeDefs[0].first, 0.); + Amg::Vector3D p2(envelopeDefs[1].second,envelopeDefs[1].first, 0.); + int clockwise = p1.cross(p2).z() < 0. ? 1 : -1; + ATH_MSG_VERBOSE(" -> determined " << ( clockwise>0 ? "clockwise" : "anti-clockwise") << " direction from (z1,r1) = " + << envelopeDefs[0].second << ", " << envelopeDefs[0].first << " and " << envelopeDefs[1].second << ", " << envelopeDefs[1].first ); + // now parse for the extended barrel + size_t irz = 0; + for ( auto& rzIter : envelopeDefs){ + if (irz > 1 && rzIter.second > 0 && rzIter.first >= enclosingVolumeRadius ) { + // maximal r-extend + enclosingExtendedVolumeRadius = envelopeDefs[irz-clockwise*2].first; + enclosingExtendedVolumeHalfZ = envelopeDefs[irz-clockwise*2].second; + } + ++irz; + } + ATH_MSG_VERBOSE(" -> Extended dimensions estimated as (r,hZ) = " << enclosingExtendedVolumeRadius << ", " << enclosingExtendedVolumeHalfZ); + + } else { + ATH_MSG_WARNING("Could not parse dimensions for extended Barrel, ignoring it."); + m_extendedEndcap = false; + } + // -------------------------------------------------------------------------------------------------- + + //generic detector has infinite alignment validity range or if exists of input volume + EventIDRange range; + + // get the inner radius and half length if a volume is provided + const Trk::CylinderVolumeBounds* cvb = 0; + const Trk::TrackingVolume* innerVol = innerVolPair.second; + if (innerVol){ + range = innerVolPair.first; + cvb = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(innerVol->volumeBounds())); + if (cvb){ + innerVolumeRadius = cvb->outerRadius(); + innerVolumeHalfZ = cvb->halflengthZ(); + ATH_MSG_VERBOSE(" -> inner cylindrical volume found with (r,hZ) = " << innerVolumeRadius << ", " << innerVolumeHalfZ); + } + } + if (!cvb){ + // if no suitable inner volume is given, divide into the configured barrel fraction + innerVolumeHalfZ = m_barrelFraction*0.5*enclosingVolumeHalfZ; + ATH_MSG_VERBOSE(" -> no (suitable) inner volume found, setting barrel/endcap fraction as configured."); + + } + + // now create the barrel-type volume wrapping around the inner volume + const Trk::TrackingVolume* cSector = m_trackingVolumeCreator->createGapTrackingVolume(vacuum, + innerVolumeRadius, enclosingVolumeRadius, + -innerVolumeHalfZ, innerVolumeHalfZ, + m_barrelLayers, + true, + m_geometryName+"::Generic::Barrel"); + cSector->registerColorCode(m_geometryColorCode); + // wrap the inner volume into a centralSector + if (cvb){ + auto centralVolumes = std::vector<const Trk::TrackingVolume*>{innerVol, cSector}; + // override barrelVolume if enclosing is needed -> memory ownership shifted to container + cSector = m_trackingVolumeCreator->createContainerTrackingVolume(centralVolumes, + vacuum, + m_geometryName+"::Containers::Central"); + } + // create the two endcaps + const Trk::TrackingVolume* nSector = m_trackingVolumeCreator->createGapTrackingVolume(vacuum, + 0., enclosingVolumeRadius, + -enclosingVolumeHalfZ, -innerVolumeHalfZ, + m_endcapLayers, + false, + m_geometryName+"::Generic::NegativeEndcap"); + nSector->registerColorCode(m_geometryColorCode); + // create the two endcaps + const Trk::TrackingVolume* pSector = m_trackingVolumeCreator->createGapTrackingVolume(vacuum, + 0., enclosingVolumeRadius, + innerVolumeHalfZ, enclosingVolumeHalfZ, + m_endcapLayers, + false, + m_geometryName+"::Generic::PositiveEndcap"); + pSector->registerColorCode(m_geometryColorCode); + + auto allVolumes = std::vector<const Trk::TrackingVolume*>(); + // if extended barrel is to be built + auto extendedVolumes = std::vector<const Trk::TrackingVolume*>(); + if ( m_extendedEndcap){ + auto names = std::vector<std::string>{ "Negative", "Positive"}; + for ( size_t it = 0; it < 2; ++it){ + // which side we are + double minZ = !it ? -enclosingExtendedVolumeHalfZ : enclosingVolumeHalfZ; + double maxZ = !it ? -enclosingVolumeHalfZ : enclosingExtendedVolumeHalfZ; + // create the extended volume (bottom part) + const Trk::TrackingVolume* exVolume = m_trackingVolumeCreator->createGapTrackingVolume( + vacuum, + 0., enclosingExtendedVolumeRadius, + minZ, maxZ, + m_extendedEndcapLayers, + false, + m_geometryName+"::Generic::Extended"+names[it]); + exVolume->registerColorCode(m_geometryColorCode); + // create the extended volume (ring part) + const Trk::TrackingVolume* exrVolume = m_trackingVolumeCreator->createGapTrackingVolume( + vacuum, + enclosingExtendedVolumeRadius, enclosingVolumeRadius, + minZ, maxZ, + m_extendedEndcapLayers, + false, + m_geometryName+"::Generic::RingExtended"+names[it]); + // sign it with one higher volume id + exrVolume->sign( Trk::GeometrySignature(int(geometrySignature())+1) ); + // pack it into a container + auto exVolumes = std::vector<const Trk::TrackingVolume*>{exVolume, exrVolume}; + const Trk::TrackingVolume* exSector = m_trackingVolumeCreator->createContainerTrackingVolume(exVolumes, + vacuum, + m_geometryName+"::Generic::"+names[it]+"ExtendedEndcap"); + // for the overall geometry + extendedVolumes.push_back(exSector); + } + } + // and now create the triple + allVolumes = extendedVolumes.size() ? std::vector<const Trk::TrackingVolume*>{extendedVolumes[0],nSector,cSector,pSector,extendedVolumes[1]} : + std::vector<const Trk::TrackingVolume*>{nSector,cSector,pSector}; + const Trk::TrackingVolume* tVolume = m_trackingVolumeCreator->createContainerTrackingVolume(allVolumes, + vacuum, + m_geometryName+"::Container"); + // now create the TrackingGeometry from the highest volume + if (tVolume) { + tGeometry = new Trk::TrackingGeometry(tVolume); + tGeometry->indexStaticLayers(geometrySignature()); + } + + + return std::make_pair(range, tGeometry); + +} + diff --git a/Tracking/TrkDetDescr/TrkDetDescrTools/src/GeometryBuilderCond.cxx b/Tracking/TrkDetDescr/TrkDetDescrTools/src/GeometryBuilderCond.cxx new file mode 100755 index 00000000000..c0d068d95a2 --- /dev/null +++ b/Tracking/TrkDetDescr/TrkDetDescrTools/src/GeometryBuilderCond.cxx @@ -0,0 +1,451 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// GeometryBuilderCond.cxx, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +// Trk include +#include "TrkDetDescrTools/GeometryBuilderCond.h" +#include "TrkDetDescrInterfaces/ITrackingVolumeBuilder.h" +#include "TrkDetDescrInterfaces/ILayerBuilderCond.h" +#include "TrkDetDescrInterfaces/ITrackingVolumeArrayCreator.h" +#include "TrkDetDescrInterfaces/ITrackingVolumeHelper.h" +#include "TrkVolumes/CylinderVolumeBounds.h" +#include "TrkGeometry/TrackingVolume.h" +#include "TrkGeometry/TrackingGeometry.h" +#include "TrkGeometry/GlueVolumesDescriptor.h" + +#ifdef TRKDETDESCR_MEMUSAGE +#include <unistd.h> +#endif + +// Amg +#include "GeoPrimitives/GeoPrimitives.h" +// STD +#include <map> +// Gaudi +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/SystemOfUnits.h" + + +// constructor +Trk::GeometryBuilderCond::GeometryBuilderCond(const std::string& t, const std::string& n, const IInterface* p) +: AthAlgTool(t,n,p), + TrackingVolumeManipulator(), +#ifdef TRKDETDESCR_MEMUSAGE + m_memoryLogger(), +#endif + m_createWorld(true), + m_navigationLevel(2), + m_worldDimension(), + m_worldMaterialProperties(), + m_trackingVolumeArrayCreator("Trk::TrackingVolumeArrayCreator/TrackingVolumeArrayCreator"), + m_trackingVolumeHelper("Trk::TrackingVolumeHelper/TrackingVolumeHelper"), + m_inDetGeometryBuilderCond("", this), + m_caloGeometry{}, + m_caloGeometryBuilderCond("", this), + m_muonGeometry{}, + m_muonGeometryBuilderCond("", this), + m_compactify(true), + m_synchronizeLayers(true) +{ + declareInterface<IGeometryBuilderCond>(this); + // by hand declarations + declareProperty("CreateWorldManually", m_createWorld); + declareProperty("NavigationLevel", m_navigationLevel); + // (1) dimension & material + declareProperty("WorldDimension", m_worldDimension); + declareProperty("WorldMaterialProperties", m_worldMaterialProperties); + // tool declarations ---------------------------------------------------------------- + declareProperty("TrackingVolumeArrayCreator", m_trackingVolumeArrayCreator); + declareProperty("TrackingVolumeHelper", m_trackingVolumeHelper); + declareProperty("InDetTrackingGeometryBuilder", m_inDetGeometryBuilderCond); + declareProperty("CaloTrackingGeometryBuilder", m_caloGeometryBuilderCond); + declareProperty("MuonTrackingGeometryBuilder", m_muonGeometryBuilderCond); + // optimize layer dimension & memory usage ------------------------------- + declareProperty("Compactify", m_compactify ); + declareProperty("SynchronizeLayers", m_synchronizeLayers ); +} + +// destructor +Trk::GeometryBuilderCond::~GeometryBuilderCond() +{} + + +// Athena standard methods +// initialize +StatusCode Trk::GeometryBuilderCond::initialize() +{ + + // Retrieve the volume array creator ---------------------------------------------------- + ATH_CHECK(m_trackingVolumeArrayCreator.retrieve()); + + // Retrieve the tracking volume helper -------------------------------------------------- + ATH_CHECK (m_trackingVolumeHelper.retrieve()); + // Geometries ============================================================================= + // (I) Inner Detector --------------------------------------------------------------------- + if (!m_inDetGeometryBuilderCond.empty()) { + ATH_CHECK(m_inDetGeometryBuilderCond.retrieve()); + } + // (C) Calorimeter -------------------------------------------------------------------------- + if (!m_caloGeometryBuilderCond.empty()) { + ATH_CHECK (m_caloGeometryBuilderCond.retrieve()); + } + // (M) Muon System ------------------------------------------------------------------------- + if (!m_muonGeometryBuilderCond.empty()) { + ATH_CHECK(m_muonGeometryBuilderCond.retrieve()); + } + + // if no world dimensions are declared, take default ones + if (!m_worldDimension.size()) + m_worldDimension = std::vector<double>{0.*Gaudi::Units::meter, 10.*Gaudi::Units::meter, 15.*Gaudi::Units::meter}; + + // if no world materials are declared, take default ones - set vacuum + if (m_worldMaterialProperties.size() < 5) + m_worldMaterialProperties = std::vector<double>{10.e10,10.e10,0., 0., 0.}; + + m_worldMaterial = Trk::Material(m_worldMaterialProperties[0], + m_worldMaterialProperties[1], + m_worldMaterialProperties[2], + m_worldMaterialProperties[3], + m_worldMaterialProperties[4]); + + ATH_MSG_DEBUG( " initialize() successful" ); + + return StatusCode::SUCCESS; +} + +// finalize +StatusCode Trk::GeometryBuilderCond::finalize() +{ + ATH_MSG_DEBUG( "finalize() successful." ); + return StatusCode::SUCCESS; +} + + +std::pair<EventIDRange, const Trk::TrackingGeometry*> Trk::GeometryBuilderCond::trackingGeometry(const EventContext& ctx, std::pair<EventIDRange, const Trk::TrackingVolume*> /*tVolPair*/) const +{ + + // the geometry to be constructed + std::pair<EventIDRange, const Trk::TrackingGeometry*> tGeometry; + if ( m_inDetGeometryBuilderCond.empty() && m_caloGeometryBuilderCond.empty() && m_muonGeometryBuilderCond.empty() ) { + + ATH_MSG_VERBOSE( "Configured to only create world TrackingVolume." ); + + Trk::VolumeBounds* worldBounds = new Trk::CylinderVolumeBounds(m_worldDimension[0], + m_worldDimension[1], + m_worldDimension[2]); + + Trk::TrackingVolume* worldVolume = new Trk::TrackingVolume(0, + worldBounds, + m_worldMaterial, + (const LayerArray*) 0, + (const TrackingVolumeArray*) 0, + "EmptyWorldVolume"); + //dummy infinite IOV range + EventIDRange range; + + // create a new geometry + tGeometry = std::make_pair(range, new Trk::TrackingGeometry(worldVolume)); + } else + tGeometry = atlasTrackingGeometry(ctx); + // sign it before you return anything + tGeometry.second->sign(geometrySignature()); + return tGeometry; + +} + + +std::pair<EventIDRange, const Trk::TrackingGeometry*> Trk::GeometryBuilderCond::atlasTrackingGeometry(const EventContext& ctx) const +{ + // the return geometry + std::pair<EventIDRange, const Trk::TrackingGeometry*> atlasTrackingGeometry; + //Set IOV range covering 0 - inf + EventIDRange range; + + // A ------------- INNER DETECTOR SECTION -------------------------------------------------------------------------------- + // get the Inner Detector and/or Calorimeter trackingGeometry + std::pair<EventIDRange, const Trk::TrackingGeometry*> inDetTrackingGeometry; + std::pair<EventIDRange, const Trk::TrackingGeometry*> caloTrackingGeometry ; + + // the volumes to be given to higher level tracking geometry builders + const Trk::TrackingVolume* inDetVolume = 0; + const Trk::TrackingVolume* caloVolume = 0; + + // mark the highest volume + const Trk::TrackingVolume* highestVolume = 0; + +#ifdef TRKDETDESCR_MEMUSAGE + m_memoryLogger.refresh(getpid()); + ATH_MSG_INFO( "[ memory usage ] Start of TrackingGeometry building: " ); + ATH_MSG_INFO( m_memoryLogger ); +#endif + + // ========================== INNER DETECTOR PART ================================================= + if (!m_inDetGeometryBuilderCond.empty()) { + // debug output + ATH_MSG_VERBOSE( "ID Tracking Geometry is going to be built." ); + // build the geometry + inDetTrackingGeometry = m_inDetGeometryBuilderCond->trackingGeometry(ctx, std::pair<EventIDRange, const Trk::TrackingVolume*>(range, nullptr)); + // check + if (inDetTrackingGeometry.second) { + // sign it + inDetTrackingGeometry.second->sign(m_inDetGeometryBuilderCond->geometrySignature()); + // check whether the world has to be created or not + if (m_createWorld || m_caloGeometry || m_muonGeometry) { + // checkout the highest InDet volume + inDetVolume = inDetTrackingGeometry.second->checkoutHighestTrackingVolume(); + // assign it as the highest volume + highestVolume = inDetVolume; + range = inDetTrackingGeometry.first; + // cleanup + delete inDetTrackingGeometry.second; + } else // -> Take the exit and return ID stand alone + atlasTrackingGeometry = inDetTrackingGeometry; + } + +#ifdef TRKDETDESCR_MEMUSAGE + m_memoryLogger.refresh(getpid()); + ATH_MSG_INFO( "[ memory usage ] After InDet TrackingGeometry building: " ); + ATH_MSG_INFO( m_memoryLogger ); +#endif + + } + + // ========================== CALORIMETER PART ================================================= + // if a Calo Geometry Builder is present -> wrap it around the ID + if (!m_caloGeometryBuilderCond.empty()) { + if (inDetVolume) + ATH_MSG_VERBOSE( "Calorimeter Tracking Geometry is going to be built with enclosed ID." ); + else + ATH_MSG_VERBOSE( "Calorimeter Tracking Geometry is going to be built stand-alone." ); + // get the InnerDetector TrackingGeometry + caloTrackingGeometry = m_caloGeometryBuilderCond->trackingGeometry(ctx, std::make_pair(inDetTrackingGeometry.first, inDetVolume)); + // if you have to create world or there is a Muon geometry builder ... + if (caloTrackingGeometry.second) { + // sign it + caloTrackingGeometry.second->sign(m_caloGeometryBuilderCond->geometrySignature()); + if (m_createWorld || m_muonGeometry){ + // check out the highest Calo volume + caloVolume = caloTrackingGeometry.second->checkoutHighestTrackingVolume(); + // assign it as the highest volume (overwrite ID) + highestVolume = caloVolume; + range = caloTrackingGeometry.first; + // cleanup + delete caloTrackingGeometry.second; + } else // -> Take the exit and return Calo back + atlasTrackingGeometry = caloTrackingGeometry; + } + +#ifdef TRKDETDESCR_MEMUSAGE + m_memoryLogger.refresh(getpid()); + ATH_MSG_INFO( "[ memory usage ] After Calo TrackingGeometry building: " ); + ATH_MSG_INFO( m_memoryLogger ); +#endif + + } + + // ========================== MUON SYSTEM PART ================================================= + // if Muon Geometry Builder is present -> wrap either ID or Calo + if (!m_muonGeometryBuilderCond.empty()) { + + std::string enclosed = "stand-alone."; + if (inDetVolume && caloVolume) + enclosed = "with encloded ID/Calo."; + else if (inDetVolume || caloVolume) + enclosed = (inDetVolume) ? "with encloded ID." : "with encloded Calo."; + ATH_MSG_VERBOSE( "Muon System Tracking Geometry is going to be built "<< enclosed ); + // there's nothing outside the muons -- wrap the calo if it exists + if (inDetVolume && !caloVolume) + atlasTrackingGeometry = m_muonGeometryBuilderCond->trackingGeometry(ctx, std::make_pair(inDetTrackingGeometry.first, inDetVolume)); + else + atlasTrackingGeometry = m_muonGeometryBuilderCond->trackingGeometry(ctx, std::make_pair(caloTrackingGeometry.first, caloVolume)); + + // sign it + if (atlasTrackingGeometry.second) + atlasTrackingGeometry.second->sign(m_muonGeometryBuilderCond->geometrySignature()); + +#ifdef TRKDETDESCR_MEMUSAGE + m_memoryLogger.refresh(getpid()); + ATH_MSG_INFO( "[ memory usage ] After Muon TrackingGeometry building: " ); + ATH_MSG_INFO( m_memoryLogger ); +#endif + + // ========================== WRAPPING SECTION FOR ID/CALO ==================================== + } else if (m_createWorld && highestVolume) { + // wrapping and world creation has been switched on + ATH_MSG_VERBOSE( "Enclosing world is going to be built for: " << highestVolume->volumeName() ); + // get the glue volumes + const Trk::GlueVolumesDescriptor& innerGlueVolumes = highestVolume->glueVolumesDescriptor(); + // some screen output + ATH_MSG_VERBOSE( "Retrieved with following glue volumes: " << innerGlueVolumes ); + // at negative face + const std::vector<const Trk::TrackingVolume*>& innerNegativeFaceVolumes = innerGlueVolumes.glueVolumes(Trk::negativeFaceXY); + // at cylinder cover + const std::vector<const Trk::TrackingVolume*>& innerCentralFaceVolumes = innerGlueVolumes.glueVolumes(Trk::cylinderCover); + // at positive face + const std::vector<const Trk::TrackingVolume*>& innerPositiveFaceVolumes = innerGlueVolumes.glueVolumes(Trk::positiveFaceXY); + + // get the dimensions + // cast them to CylinderVolumeBounds + const Trk::CylinderVolumeBounds* innerVolumeBounds = dynamic_cast<const Trk::CylinderVolumeBounds*>(&(highestVolume->volumeBounds())); + if (!innerVolumeBounds) ATH_MSG_WARNING( "atlasTrackingGeometry() ... dynamic cast to innerVolumeBounds failed!" ); + double innerVolumeOuterR = innerVolumeBounds ? innerVolumeBounds->outerRadius() : 0; + double innerVolumeHalflengthZ = innerVolumeBounds ? innerVolumeBounds->halflengthZ() : 0; + // Hierarchy after enclosing + // + // AtlasWorldVolume: + // AtlasInnerCylinder + // AtlasInnerNegativeSector + // InnerEnclosedVolume (can be ID/Calo) + // AtlasOuterNegativeSector + // AtlasOuterTube + // B -------------- BUILD WORLD AROUND for ID stand alone applications + + double innerCylinderSectorHalflengthZ = 0.5*(m_worldDimension[2] - innerVolumeHalflengthZ); + Trk::CylinderVolumeBounds* innerCylinderSectorBounds = + new Trk::CylinderVolumeBounds(0., innerVolumeOuterR, innerCylinderSectorHalflengthZ); + + double innerCylinderSectorPositionZ = fabs(m_worldDimension[2]-innerCylinderSectorHalflengthZ); + + // the AtlasInnerNegativeSector + Amg::Transform3D* atlasInnerNegativeSectorTransf = new Amg::Transform3D; + (*atlasInnerNegativeSectorTransf) = Amg::Translation3D(0.,0.,-innerCylinderSectorPositionZ); + Trk::TrackingVolume* atlasInnerNegativeSector = new Trk::TrackingVolume( + atlasInnerNegativeSectorTransf, + innerCylinderSectorBounds, + m_worldMaterial, + (const LayerArray*) 0, + (const TrackingVolumeArray*) 0, + "AtlasInnerNegativeSector"); + + // the AtlasInnerPositiveSector + Amg::Transform3D* atlasInnerPositiveSectorTransf = new Amg::Transform3D; + (*atlasInnerPositiveSectorTransf) = Amg::Translation3D(0.,0.,innerCylinderSectorPositionZ); + Trk::TrackingVolume* atlasInnerPositiveSector = new Trk::TrackingVolume( + atlasInnerPositiveSectorTransf, + innerCylinderSectorBounds->clone(), + m_worldMaterial, + (const LayerArray*) 0, + (const TrackingVolumeArray*) 0, + "AtlasInnerPositiveSector"); + + ATH_MSG_VERBOSE( "Inner Negative/Positive Sectors built successfully." ); + + // create the subvolume Array + auto atlasInnerSectorVolumes = std::vector<const Trk::TrackingVolume*>{atlasInnerNegativeSector,highestVolume,atlasInnerPositiveSector}; + + ATH_MSG_VERBOSE( "Create the Atlas Inner Sector volumes. " ); + Trk::BinnedArray<Trk::TrackingVolume>* atlasInnerSectorVolumeArray = m_trackingVolumeArrayCreator ? + m_trackingVolumeArrayCreator->cylinderVolumesArrayInZ(atlasInnerSectorVolumes) : 0; + + + // Atlas inner Sector bounds + Trk::CylinderVolumeBounds* innerSectorBounds = + new Trk::CylinderVolumeBounds(0., innerVolumeOuterR, m_worldDimension[2]); + // build the Tracking volumes + Trk::TrackingVolume* atlasInnerSector = new Trk::TrackingVolume(0, + innerSectorBounds, + m_worldMaterial, + 0,atlasInnerSectorVolumeArray, + "AtlasInnerSector"); + + // Atlas outer Sector + Trk::CylinderVolumeBounds* outerSectorBounds = + new Trk::CylinderVolumeBounds(innerVolumeOuterR, m_worldDimension[1], m_worldDimension[2]); + Trk::TrackingVolume* atlasOuterSector = new Trk::TrackingVolume(0, + outerSectorBounds, + m_worldMaterial, + (const LayerArray*) 0, + (const TrackingVolumeArray*) 0, + "AtlasOuterSector"); + + ATH_MSG_VERBOSE( "Atlas Inner/Outer Sectors built successfully." ); + + // create the array of Inner and Outer sector + auto atlasVolumes = std::vector<const Trk::TrackingVolume*>{atlasInnerSector, atlasOuterSector}; + + Trk::BinnedArray<Trk::TrackingVolume>* atlasVolumeArray = m_trackingVolumeArrayCreator ? + m_trackingVolumeArrayCreator->cylinderVolumesArrayInR(atlasVolumes) : 0; + + // create the Atlas volume bounds + Trk::CylinderVolumeBounds* atlasBounds = new Trk::CylinderVolumeBounds(0., m_worldDimension[1], m_worldDimension[2]); + + // create the Atlas TrackingVolume + Trk::TrackingVolume* atlasVolume = new Trk::TrackingVolume(0, + atlasBounds, + m_worldMaterial, + 0,atlasVolumeArray, + "Atlas"); + + ATH_MSG_VERBOSE( "Atlas Tracking World volume built successfully." ); + + + // glue the inner sector to be complete + m_trackingVolumeHelper->glueTrackingVolumes( *atlasInnerNegativeSector, Trk::positiveFaceXY, + innerNegativeFaceVolumes, Trk::negativeFaceXY ); + + m_trackingVolumeHelper->glueTrackingVolumes( *atlasInnerPositiveSector, Trk::negativeFaceXY, + innerPositiveFaceVolumes, Trk::positiveFaceXY ); + + ATH_MSG_VERBOSE( "Atlas Inner Sector glued successfully together." ); + + // iterators to the face volumes + auto volIter = innerCentralFaceVolumes.begin(); + auto volIterEnd = innerCentralFaceVolumes.end(); + + // glue outer and inner sector together + std::vector<const Trk::TrackingVolume*> atlasInnerOuterVolumes; + atlasInnerOuterVolumes.push_back(atlasInnerNegativeSector); + for ( ; volIter != volIterEnd; ++volIter) + if (*volIter) atlasInnerOuterVolumes.push_back(*volIter); + atlasInnerOuterVolumes.push_back(atlasInnerPositiveSector); + + m_trackingVolumeHelper->glueTrackingVolumes(*atlasOuterSector, Trk::tubeInnerCover, + atlasInnerOuterVolumes, Trk::tubeOuterCover); + + ATH_MSG_VERBOSE( "Atlas Inner/Outer Sector glued successfully together." ); + + // job done -> create the TrackingGeometry + atlasTrackingGeometry.second = new Trk::TrackingGeometry(atlasVolume); + + atlasTrackingGeometry.first = range; + + // detailed information about this tracking geometry + ATH_MSG_VERBOSE( "Atlas TrackingGeometry built with following parameters : "); + //ATH_MSG_VERBOSE( " - TrackingVolume containers : " << atlasTrackingGeometry->numberOfContainerVolumes() ); + //ATH_MSG_VERBOSE( " - TrackingVolume at navigation level : " << atlasTrackingGeometry->numberOfContainerVolumes() ); + //ATH_MSG_VERBOSE( " - Contained static layers : " << atlasTrackingGeometry->boundaryLayers().size()); + ATH_MSG_VERBOSE( " - Unique material layers on boundaries : " << atlasTrackingGeometry.second->boundaryLayers().size()); + +#ifdef TRKDETDESCR_MEMUSAGE + m_memoryLogger.refresh(getpid()); + ATH_MSG_INFO( "[ memory usage ] After Outer Sector TrackingGeometry building: " ); + ATH_MSG_INFO( m_memoryLogger ); +#endif + + } + + if (atlasTrackingGeometry.second) { + if (m_navigationLevel < 3) + atlasTrackingGeometry.second->registerNavigationLevel( Trk::NavigationLevel(m_navigationLevel)); + } + else ATH_MSG_WARNING( "atlasTrackingGeometry() ... atlasTrackingGeometry = 0, could not call registerNavigationLevel and propagateMagneticFieldProperties" ); + +#ifdef TRKDETDESCR_MEMUSAGE + m_memoryLogger.refresh(getpid()); + ATH_MSG_INFO( "[ memory usage ] End of TrackingGeometry building: " ); + ATH_MSG_INFO( m_memoryLogger ); +#endif + + // synchronize the layers + if (atlasTrackingGeometry.second) { + if (m_synchronizeLayers) atlasTrackingGeometry.second->synchronizeLayers(msg()); + + // compactify if configured to do so + if (m_compactify) atlasTrackingGeometry.second->compactify(msg()); + } + return atlasTrackingGeometry; +} diff --git a/Tracking/TrkDetDescr/TrkDetDescrTools/src/InputLayerMaterialProvider.cxx b/Tracking/TrkDetDescr/TrkDetDescrTools/src/InputLayerMaterialProvider.cxx index b17891b7150..f45dbb13139 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrTools/src/InputLayerMaterialProvider.cxx +++ b/Tracking/TrkDetDescr/TrkDetDescrTools/src/InputLayerMaterialProvider.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -56,7 +56,7 @@ StatusCode Trk::InputLayerMaterialProvider::initialize() { } // Processor Action to work on TrackingGeometry -StatusCode Trk::InputLayerMaterialProvider::process(const Trk::TrackingGeometry& tgeo) { +StatusCode Trk::InputLayerMaterialProvider::process(const Trk::TrackingGeometry& tgeo) const { ATH_MSG_VERBOSE("Start processing the TrackingGeometry recursively"); // retrieve the highest tracking volume @@ -71,7 +71,7 @@ StatusCode Trk::InputLayerMaterialProvider::process(const Trk::TrackingGeometry& } // Processor Action to work on TrackingVolumes -StatusCode Trk::InputLayerMaterialProvider::process(const Trk::TrackingVolume& tvol, size_t level) { +StatusCode Trk::InputLayerMaterialProvider::process(const Trk::TrackingVolume& tvol, size_t level) const { std::stringstream displayBuffer; for (size_t il = 0; il < level; ++il) displayBuffer << " "; @@ -118,7 +118,7 @@ StatusCode Trk::InputLayerMaterialProvider::process(const Trk::TrackingVolume& t } // Processor Action to work on Layers -StatusCode Trk::InputLayerMaterialProvider::process(const Trk::Layer& lay, size_t level) { +StatusCode Trk::InputLayerMaterialProvider::process(const Trk::Layer& lay, size_t level) const { // skip Layers w/o material if (!lay.layerMaterialProperties()) @@ -142,7 +142,7 @@ StatusCode Trk::InputLayerMaterialProvider::process(const Trk::Layer& lay, size_ } // Processor Action to work on Surfaces -StatusCode Trk::InputLayerMaterialProvider::process(const Trk::Surface&, size_t) { +StatusCode Trk::InputLayerMaterialProvider::process(const Trk::Surface&, size_t) const { return StatusCode::SUCCESS; } diff --git a/Tracking/TrkDetDescr/TrkDetDescrTools/src/LayerMaterialProvider.cxx b/Tracking/TrkDetDescr/TrkDetDescrTools/src/LayerMaterialProvider.cxx index ecd20cec315..6054b6d539c 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrTools/src/LayerMaterialProvider.cxx +++ b/Tracking/TrkDetDescr/TrkDetDescrTools/src/LayerMaterialProvider.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ /////////////////////////////////////////////////////////////////// @@ -36,7 +36,7 @@ Trk::LayerMaterialProvider::~LayerMaterialProvider() // Processor Action to work on TrackingGeometry -StatusCode Trk::LayerMaterialProvider::process(const Trk::TrackingGeometry& tgeo) { +StatusCode Trk::LayerMaterialProvider::process(const Trk::TrackingGeometry& tgeo) const{ ATH_MSG_VERBOSE("Start processing the TrackingGeometry recursively"); // retrieve the highest tracking volume @@ -81,14 +81,16 @@ StatusCode Trk::LayerMaterialProvider::process(const Trk::TrackingGeometry& tgeo } // Processor Action to work on TrackingVolumes -StatusCode Trk::LayerMaterialProvider::process(const Trk::TrackingVolume& tvol, size_t level) { +StatusCode Trk::LayerMaterialProvider::process(const Trk::TrackingVolume& tvol, size_t level) const { // load the material map if not done yet - if (!m_layerMaterialMap){ - if (loadMaterialMap().isFailure()){ - ATH_MSG_DEBUG( "Problems loading hte LayerMaterialMap - check name or call sequence." ); - return StatusCode::FAILURE; - } + bool loadMapFailed = false; + std::call_once(m_loadMapOnceFlag, [&](){ + loadMapFailed = loadMaterialMap().isFailure(); + }); + if (loadMapFailed){ + ATH_MSG_DEBUG( "Problems loading the LayerMaterialMap - check name or call sequence." ); + return StatusCode::FAILURE; } std::stringstream displayBuffer; @@ -148,14 +150,16 @@ StatusCode Trk::LayerMaterialProvider::process(const Trk::TrackingVolume& tvol, } // Processor Action to work on Layers -StatusCode Trk::LayerMaterialProvider::process(const Trk::Layer& lay, size_t level) { +StatusCode Trk::LayerMaterialProvider::process(const Trk::Layer& lay, size_t level) const { // load the material map if not done yet - if (!m_layerMaterialMap){ - if (loadMaterialMap().isFailure()){ - ATH_MSG_WARNING( "Problems loading the LayerMaterialMap - check name or call sequence." ); - return StatusCode::FAILURE; - } + bool loadMapFailed = false; + std::call_once(m_loadMapOnceFlag, [&](){ + loadMapFailed = loadMaterialMap().isFailure(); + }); + if (loadMapFailed){ + ATH_MSG_DEBUG( "Problems loading the LayerMaterialMap - check name or call sequence." ); + return StatusCode::FAILURE; } // is the pointer still null? if (!m_layerMaterialMap) { @@ -190,12 +194,12 @@ StatusCode Trk::LayerMaterialProvider::process(const Trk::Layer& lay, size_t lev } // Processor Action to work on Surfaces -StatusCode Trk::LayerMaterialProvider::process(const Trk::Surface&, size_t) { +StatusCode Trk::LayerMaterialProvider::process(const Trk::Surface&, size_t) const{ return StatusCode::SUCCESS; } // load the material map from StoreGate -StatusCode Trk::LayerMaterialProvider::loadMaterialMap() { +StatusCode Trk::LayerMaterialProvider::loadMaterialMap() const { // ------------------------------------------------------------------------------- if (detStore()->retrieve(m_layerMaterialMap, m_layerMaterialMapName).isFailure()){ diff --git a/Tracking/TrkDetDescr/TrkDetDescrTools/src/LayerProviderCond.cxx b/Tracking/TrkDetDescr/TrkDetDescrTools/src/LayerProviderCond.cxx new file mode 100644 index 00000000000..350c99121c5 --- /dev/null +++ b/Tracking/TrkDetDescr/TrkDetDescrTools/src/LayerProviderCond.cxx @@ -0,0 +1,114 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// LayerProviderCond.cxx, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +// STL +#include <sstream> +// Trk include +#include "TrkDetDescrTools/LayerProviderCond.h" +#include "TrkDetDescrInterfaces/ILayerBuilderCond.h" +#include "TrkGeometry/Layer.h" +#include "TrkGeometry/CylinderLayer.h" +#include "TrkGeometry/DiscLayer.h" + +// constructor +Trk::LayerProviderCond::LayerProviderCond(const std::string& t, const std::string& n, const IInterface* p) +: AthAlgTool(t,n,p) +{ + declareInterface<Trk::ILayerProviderCond>(this); + + // Name specification from outside + declareProperty("LayerBuilder", m_layerBuilder); + +} + +// destructor +Trk::LayerProviderCond::~LayerProviderCond() +{} + +// initialize +StatusCode Trk::LayerProviderCond::initialize() +{ + if (m_layerBuilder.retrieve().isFailure()){ + ATH_MSG_WARNING("Could not retrieve layer builder"); + } + return StatusCode::SUCCESS; +} + +/** LayerBuilderCond interface method - returning the layers at negative side */ +std::pair<EventIDRange, const std::vector< const Trk::Layer*> > Trk::LayerProviderCond::negativeLayers(const EventContext& ctx) const +{ + // this will fill the cache with positive layers + return discLayers(ctx, -1); +} + +/** LayerBuilderCond interface method - returning the central layers */ +std::pair<EventIDRange, const std::vector< const Trk::Layer* > > Trk::LayerProviderCond::centralLayers(const EventContext& ctx) const +{ + // central layers + std::vector< const Trk::Layer* > cLayers; + // retrieving the cylinder layers from the layer builder + std::pair<EventIDRange, const std::vector< const Trk::CylinderLayer* >* > cylinderLayersPair = m_layerBuilder->cylindricalLayers(ctx); + auto cylinderLayers = cylinderLayersPair.second; + // loop over it and push into the return vector; + if (cylinderLayers){ + for (auto& cL : (*cylinderLayers)) + cLayers.push_back(cL); + } + // memory cleanup + delete cylinderLayers; + // and return + return std::make_pair(cylinderLayersPair.first, cLayers); +} + +/** LayerBuilderCond interface method - returning the layers at negative side */ +std::pair<EventIDRange,const std::vector< const Trk::Layer*> > Trk::LayerProviderCond::positiveLayers(const EventContext& ctx) const +{ + // this will fill the cache with negative layers + return discLayers(ctx, 1); +} + +/** LayerBuilderCond interface method - returning the layers at negative side */ +std::pair<EventIDRange, const std::vector< const Trk::Layer* > > Trk::LayerProviderCond::discLayers(const EventContext& ctx, int posneg) const +{ + // get the disc layers + std::vector < const Trk::Layer* > dLayers; + // retrieving the cylinder layers from the layer builder + std::pair<EventIDRange, const std::vector<const Trk::DiscLayer*>*> discLayersPair = m_layerBuilder->discLayers(ctx); + auto discLayers = discLayersPair.second; + // loop and fill either cache or dLayers + if (discLayers){ + // loop over and push into the return/cache vector + for (auto& dL : (*discLayers) ){ + // get the center posituion + double zpos = dL->surfaceRepresentation().center().z(); + if (posneg > 0){ + // configured to provide positive and cache negative + if (zpos > 0.) dLayers.push_back(dL); + } else { + // configured to provide negative and cache positive + if (zpos < 0.) dLayers.push_back(dL); + } + } + } + // memory cleanup + delete discLayers; + // and return + return std::make_pair(discLayersPair.first, dLayers); +} + + +// finalize +StatusCode Trk::LayerProviderCond::finalize() +{ + return StatusCode::SUCCESS; +} + +const std::string& Trk::LayerProviderCond::identification() const +{ + return m_layerBuilder->identification(); +} diff --git a/Tracking/TrkDetDescr/TrkDetDescrTools/src/components/TrkDetDescrTools_entries.cxx b/Tracking/TrkDetDescr/TrkDetDescrTools/src/components/TrkDetDescrTools_entries.cxx index 0cff6b5e051..3a1fa376857 100644 --- a/Tracking/TrkDetDescr/TrkDetDescrTools/src/components/TrkDetDescrTools_entries.cxx +++ b/Tracking/TrkDetDescr/TrkDetDescrTools/src/components/TrkDetDescrTools_entries.cxx @@ -12,6 +12,10 @@ #include "TrkDetDescrTools/TrackingVolumeArrayCreator.h" #include "TrkDetDescrTools/TrackingVolumeHelper.h" +#include "TrkDetDescrTools/GeometryBuilderCond.h" +#include "TrkDetDescrTools/GenericGeometryBuilderCond.h" +#include "TrkDetDescrTools/LayerProviderCond.h" + using namespace Trk; DECLARE_COMPONENT( CylinderVolumeCreator ) @@ -28,3 +32,6 @@ DECLARE_COMPONENT( InputLayerMaterialProvider ) DECLARE_COMPONENT( TrackingVolumeArrayCreator ) DECLARE_COMPONENT( TrackingVolumeHelper ) +DECLARE_COMPONENT( GeometryBuilderCond ) +DECLARE_COMPONENT( GenericGeometryBuilderCond ) +DECLARE_COMPONENT( LayerProviderCond ) diff --git a/Tracking/TrkDetDescr/TrkGeometry/TrkGeometry/TrackingGeometry.h b/Tracking/TrkDetDescr/TrkGeometry/TrkGeometry/TrackingGeometry.h index 02efbc103fc..71b577d0532 100755 --- a/Tracking/TrkDetDescr/TrkGeometry/TrkGeometry/TrackingGeometry.h +++ b/Tracking/TrkDetDescr/TrkGeometry/TrkGeometry/TrackingGeometry.h @@ -60,6 +60,9 @@ namespace Trk { /** Give the GeometryBuilder friend rights */ friend class GeometryBuilder; friend class IGeometryBuilder; + + friend class GeometryBuilderCond; + friend class IGeometryBuilderCond; public : /** Constructor */ @@ -212,5 +215,8 @@ namespace Trk { } // end of namespace CLASS_DEF(Trk::TrackingGeometry, 167645219, 1) +#include "AthenaKernel/CondCont.h" +CONDCONT_DEF( Trk::TrackingGeometry , 119021535 ); + #endif //TRKGEOMETRY_TRACKINGGEOMETRY_H -- GitLab