From 36bd6babd8e8ad847f6be517951c5f79facc467b Mon Sep 17 00:00:00 2001 From: Andre Sailer Date: Wed, 14 Feb 2024 17:08:00 +0100 Subject: [PATCH 01/42] CMake: add shim for LCIO::lcio --- CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d467551ae..73bd2a448 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,15 @@ message ( STATUS "ROOT_VERSION: ${ROOT_VERSION}" ) find_package( Geant4 REQUIRED ) find_package( LCIO REQUIRED) +# Shim for older LCIO versions +if(NOT TARGET LCIO::lcio) + add_library(LCIO::lcio INTERFACE IMPORTED GLOBAL) + set_target_properties(LCIO::lcio + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${LCIO_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${LCIO_LIBRARIES}" + ) +endif() add_subdirectory(detectorSegmentations) add_subdirectory(detectorCommon) From 9889d01ba16f5eac9eed65c7f469eacacc856aca Mon Sep 17 00:00:00 2001 From: Andre Sailer Date: Fri, 16 Feb 2024 11:36:27 +0100 Subject: [PATCH 02/42] LinearSortingPolicy: ignore unavailable extension error and adapt treatment for it --- plugins/LinearSortingPolicy.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/LinearSortingPolicy.cpp b/plugins/LinearSortingPolicy.cpp index 41ca7d9e4..dde46cf9a 100644 --- a/plugins/LinearSortingPolicy.cpp +++ b/plugins/LinearSortingPolicy.cpp @@ -91,9 +91,13 @@ namespace { dd4hep::rec::DoubleParameters* para = nullptr; try { // use existing map, or create a new one - para = ddsurf->detElement().extension(); + para = ddsurf->detElement().extension(false); + if(not para) { + para = new dd4hep::rec::DoubleParameters; + ddsurf->detElement().addExtension(para); + } para->doubleParameters["SortingPolicy"] = rValue; - } catch(...){ + } catch(...) { para = new dd4hep::rec::DoubleParameters; para->doubleParameters["SortingPolicy"] = rValue; ddsurf->detElement().addExtension(para); From 92ffe4a35347524eaa351932daab774f7d067102 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori <39376142+giovannimarchiori@users.noreply.github.com> Date: Wed, 21 Feb 2024 16:04:34 +0100 Subject: [PATCH 03/42] Update some ALLEGRO xml config files (#318) --- FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/DectEmptyMaster.xml | 6 +++--- .../ECalBarrel_thetamodulemerged_calibration.xml | 6 +++++- .../ECalBarrel_thetamodulemerged_upstream.xml | 8 ++++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/DectEmptyMaster.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/DectEmptyMaster.xml index a5ad3e23b..263dcce4d 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/DectEmptyMaster.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/DectEmptyMaster.xml @@ -6,8 +6,8 @@ - - + + - + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_calibration.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_calibration.xml index d69ba26f9..027f20800 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_calibration.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_calibration.xml @@ -102,6 +102,10 @@ + + + + @@ -136,4 +140,4 @@ - + \ No newline at end of file diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_upstream.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_upstream.xml index ee39e57a5..962746659 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_upstream.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_upstream.xml @@ -25,7 +25,7 @@ - + @@ -78,7 +78,7 @@ - + system:4,cryo:1,type:3,subtype:3,layer:8,module:11,theta:10 @@ -102,6 +102,10 @@ + + + + From acfef0114df55991c0858f88b35af895193aba3e Mon Sep 17 00:00:00 2001 From: Brieuc Francois Date: Thu, 22 Feb 2024 22:23:54 +0100 Subject: [PATCH 04/42] Increase timeOut for IDEA test (#323) --- lcgeoTests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcgeoTests/CMakeLists.txt b/lcgeoTests/CMakeLists.txt index 909fbdee6..5df4cfc31 100644 --- a/lcgeoTests/CMakeLists.txt +++ b/lcgeoTests/CMakeLists.txt @@ -84,7 +84,7 @@ SET_TESTS_PROPERTIES( t_${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "Except SET( test_name "test_IDEA_o1_v02" ) ADD_TEST( t_${test_name} "${CMAKE_INSTALL_PREFIX}/bin/run_test_${PackageName}.sh" ddsim --compactFile=${CMAKE_CURRENT_SOURCE_DIR}/../FCCee/IDEA/compact/IDEA_o1_v02/IDEA_o1_v02.xml --runType=batch -G -N=1 --outputFile=testIDEA_o1_v02.slcio ) -SET_TESTS_PROPERTIES( t_${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "Exception;EXCEPTION;ERROR;Error" TIMEOUT 240) +SET_TESTS_PROPERTIES( t_${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "Exception;EXCEPTION;ERROR;Error" TIMEOUT 360) #-------------------------------------------------- # test for ALLEGRO o1 v02 From c5cced6b647a49d1abbabdde79f4e4d43b1db899 Mon Sep 17 00:00:00 2001 From: jmcarcell Date: Fri, 23 Feb 2024 08:01:46 +0100 Subject: [PATCH 05/42] Bump version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73bd2a448..5e2c52bc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ project(${PackageName}) # project version SET( ${PackageName}_VERSION_MAJOR 0 ) -SET( ${PackageName}_VERSION_MINOR 19 ) +SET( ${PackageName}_VERSION_MINOR 20 ) SET( ${PackageName}_VERSION_PATCH 0 ) SET( ${PackageName}_VERSION "${${PackageName}_VERSION_MAJOR}.${${PackageName}_VERSION_MINOR}" ) From 7c3d24111af17c336a6c26cade61788ff1740f1d Mon Sep 17 00:00:00 2001 From: Juan Miguel Carceller <22276694+jmcarcell@users.noreply.github.com> Date: Fri, 23 Feb 2024 08:02:48 +0100 Subject: [PATCH 06/42] Release Notes for v00-20-00 --- doc/ReleaseNotes.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/doc/ReleaseNotes.md b/doc/ReleaseNotes.md index 872c6ddd6..94ec37b5d 100644 --- a/doc/ReleaseNotes.md +++ b/doc/ReleaseNotes.md @@ -1,3 +1,47 @@ +# v00-20-00 + +* 2024-02-22 BrieucF ([PR#323](https://github.com/key4hep/k4geo/pull/323)) + - Increase IDEA test timeout + +* 2024-02-21 Giovanni Marchiori ([PR#318](https://github.com/key4hep/k4geo/pull/318)) + * ALLEGRO: Update some xml config files + +* 2024-02-16 Andre Sailer ([PR#320](https://github.com/key4hep/k4geo/pull/320)) + - CMake: Add shim for older LCIO versions that do not have LCIO::lcio yet + - LinearSortingPolicy: adapt check for existing extension to silence error message from DD4hep + +* 2024-02-09 Andre Sailer ([PR#317](https://github.com/key4hep/k4geo/pull/317)) + - ALLEGRO: EcalBarrel: fix the length of the Z extent for the calorimeter data extension for reconstruction + +* 2024-02-06 BrieucF ([PR#315](https://github.com/key4hep/k4geo/pull/315)) + - [ALLEGRO_o1_v02] Replace the simplified drift chamber with the detailed one + - [TESTS] Add a test for ALLEGRO_o1_v02 + - [ALLEGRO_o1_v02] File and variable renaming plus propagation of overlap fix to upstream and calibration xml's + +* 2024-02-06 Juraj Smiesko ([PR#309](https://github.com/key4hep/k4geo/pull/309)) + - CMake: Add printing of "Found k4geo" message in downstream projects picking up k4geoConfig.cmake + +* 2024-01-18 jmcarcell ([PR#310](https://github.com/key4hep/k4geo/pull/310)) + - Change LCIO::LCIO to LCIO::lcio. The target provided by LCIO is LCIO::lcio; DD4hep provides LCIO::LCIO so building without DD4hep and using LCIO::LCIO doesn't seem to work. + +* 2024-01-09 Jana ([PR#308](https://github.com/key4hep/k4geo/pull/308)) + - fixing the overlaps in ALLEGRO Ecal barrel geometry by increasing the LAr bath volume. + +* 2023-12-18 Swathi Sasikumar ([PR#312](https://github.com/key4hep/k4geo/pull/312)) + - CLD_o4_v05: The name of the inclined calorimeter was given as `EmCaloBarrelInclined` before. This is now changed to the latest naming convention as `ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v01` + - ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v01: The units for cell sizes has been added to the CaloLayerData ensure that they are given correctly and not mistaken due to confusion in units. now they are represented in mm. + +* 2023-12-14 BrieucF ([PR#307](https://github.com/key4hep/k4geo/pull/307)) + - Added DriftChamber_o1_v01, a first version of the detailed IDEA drift chamber to enable further technical developments (digitization, tracking, PFlow, ...) + +* 2023-12-13 Giovanni Marchiori ([PR#304](https://github.com/key4hep/k4geo/pull/304)) + - Code changes related to k4geo migration of FCC segmentation classes and related utilities + - Also moves HCal readout for Allegro from eta-based to theta-based + - Basically a rebasing of https://github.com/key4hep/k4geo/pull/296 after https://github.com/key4hep/k4geo/pull/298 was merged + +* 2023-12-12 BrieucF ([PR#311](https://github.com/key4hep/k4geo/pull/311)) + - Changed the sensitive detector type of the ALLEGO simplified drift chamber to be able to run with ddsim + # v00-19-00 * 2023-11-22 alvarotd ([PR#289](https://github.com/key4hep/k4geo/pull/289)) From 032f294a5b04871c4eb6ad0300a4d6ee09b32324 Mon Sep 17 00:00:00 2001 From: jmcarcell Date: Sun, 25 Feb 2024 09:25:07 +0100 Subject: [PATCH 07/42] Update the key4hep-build workflow; previous commit: Release Notes for v00-20-00 --- .github/workflows/key4hep-build.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/key4hep-build.yaml b/.github/workflows/key4hep-build.yaml index 3f9007f09..5ba768a48 100644 --- a/.github/workflows/key4hep-build.yaml +++ b/.github/workflows/key4hep-build.yaml @@ -6,6 +6,9 @@ on: - main pull_request: workflow_dispatch: + schedule: + - cron: '17 5 * * *' + jobs: build: From bda060c72afb560b5ebe8c1f206efc71d74e771c Mon Sep 17 00:00:00 2001 From: Juan Miguel Carceller <22276694+jmcarcell@users.noreply.github.com> Date: Sun, 25 Feb 2024 19:20:35 +0100 Subject: [PATCH 08/42] Remove the old key4hep build workflow (#324) --- .github/workflows/key4hep.yml | 43 ----------------------------------- 1 file changed, 43 deletions(-) delete mode 100644 .github/workflows/key4hep.yml diff --git a/.github/workflows/key4hep.yml b/.github/workflows/key4hep.yml deleted file mode 100644 index e41729bd8..000000000 --- a/.github/workflows/key4hep.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: key4hep-stack - -on: [push, pull_request] - -jobs: - test: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - SETUP: ['/cvmfs/sw.hsf.org/key4hep/setup.sh', '/cvmfs/sw-nightlies.hsf.org/key4hep/setup.sh'] - steps: - - uses: actions/checkout@v3 - - uses: cvmfs-contrib/github-action-cvmfs@v3 - - name: Start container - run: | - docker run -it --name CI_container -v ${GITHUB_WORKSPACE}:/Package -v /cvmfs:/cvmfs:shared -d ghcr.io/aidasoft/centos7:latest /bin/bash - - name: CMake Configure - run: | - docker exec CI_container /bin/bash -c 'cd Package;\ - mkdir -p build install;\ - source ${{ matrix.SETUP }};\ - cd build;\ - cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_CXX_STANDARD=17 -DCMAKE_CXX_FLAGS=" -fdiagnostics-color=always " -G Ninja ..;' - - name: Compile - run: | - docker exec CI_container /bin/bash -c 'cd ./Package;\ - source ${{ matrix.SETUP }};\ - cd build;\ - ninja -k0;' - - name: Install - run: | - docker exec CI_container /bin/bash -c 'cd ./Package;\ - source ${{ matrix.SETUP }};\ - cd build;\ - ninja -k0 install;' - - name: Test - run: | - docker exec CI_container /bin/bash -c 'cd ./Package;\ - source ${{ matrix.SETUP }};\ - cd build;\ - ninja -k0 && ctest --output-on-failure;' - From e6ca6638659534d6927e2882a340fe739f6f1516 Mon Sep 17 00:00:00 2001 From: Juan Miguel Carceller <22276694+jmcarcell@users.noreply.github.com> Date: Sun, 25 Feb 2024 20:40:54 +0100 Subject: [PATCH 09/42] Clean up unused variables (#302) --- ...l_NobleLiquid_InclinedTrapezoids_o1_v01_geo.cpp | 6 ++---- detector/calorimeter/ECalBarrel_o2_v01_geo.cpp | 10 ---------- detector/calorimeter/ECalEndcap_o1_v01_geo.cpp | 2 -- .../calorimeter/GenericCalBarrel_o1_v01_geo.cpp | 10 ---------- detector/calorimeter/HCalBarrel_o1_v01_geo.cpp | 12 +----------- .../HCalThreePartsEndcap_o1_v01_geo.cpp | 7 ------- detector/calorimeter/HCalTileBarrel_o1_v01_geo.cpp | 3 --- detector/calorimeter/SECalEndcap_o1_v01_geo.cpp | 2 -- detector/calorimeter/SEcal05_ECRing.cpp | 2 +- .../calorimeter/SteppedMuonBarrel_o2_v02_geo.cpp | 9 --------- detector/calorimeter/YokeBarrel_o1_v01_geo.cpp | 12 +----------- detector/calorimeter/YokeEndcap_o1_v01_geo.cpp | 12 +----------- .../tracker/VertexBarrel_detailed_o1_v01_geo.cpp | 14 +++++++------- .../tracker/VertexEndcap_detailed_o1_v01_geo.cpp | 7 ++----- 14 files changed, 15 insertions(+), 93 deletions(-) diff --git a/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v01_geo.cpp b/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v01_geo.cpp index d0abe7645..2f3777384 100644 --- a/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v01_geo.cpp +++ b/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v01_geo.cpp @@ -574,15 +574,13 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, dd4hep::xml::setDetectorTypeFlag(xmlDetElem, caloDetElem); dd4hep::rec::MaterialManager matMgr(envelopeVol); dd4hep::rec::LayeredCalorimeterData::Layer caloLayer; - double nRadiationLengths = 0.; - double nInteractionLengths = 0.; double rad_first = Rmin; double rad_last = 0; double scale_fact = dR / (-Rmin * cos(angle) + sqrt(pow(Rmax, 2) - pow(Rmin * sin(angle), 2))); // since the layer height is given along the electrode and not along the radius it needs to be scaled to get the values of layer height radially std::cout << "Scaling factor " << scale_fact << std::endl; - for (auto il = 0; il < layerHeight.size(); il++) { + for (size_t il = 0; il < layerHeight.size(); il++) { double thickness_sen = 0.; double absorberThickness = 0.; @@ -600,7 +598,7 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, const double value_of_lambda = layerHeight[il] / nInteractionLengths; std::string str1("LAr"); - for (auto imat = 0; imat < materials.size(); imat++) { + for (size_t imat = 0; imat < materials.size(); imat++) { std::string str2(materials.at(imat).first.name()); if (str1.compare(str2) == 0){ diff --git a/detector/calorimeter/ECalBarrel_o2_v01_geo.cpp b/detector/calorimeter/ECalBarrel_o2_v01_geo.cpp index 2cce0befa..c05626be8 100644 --- a/detector/calorimeter/ECalBarrel_o2_v01_geo.cpp +++ b/detector/calorimeter/ECalBarrel_o2_v01_geo.cpp @@ -71,8 +71,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s string det_type = x_det.typeStr(); Material air = theDetector.air(); double totalThickness = layering.totalThickness(); - int totalRepeat = 0; - int totalSlices = 0; double gap = xml_dim_t(x_det).gap(); int nsides = dim.numsides(); @@ -107,14 +105,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s caloData->gap1 = 0.; //FIXME caloData->gap2 = 0.; //FIXME - - for (xml_coll_t c(x_det, _U(layer)); c; ++c) { - xml_comp_t x_layer = c; - int repeat = x_layer.repeat(); - totalRepeat += repeat; - totalSlices += x_layer.numChildren(_U(slice)); - } - // --- create an envelope volume and position it into the world --------------------- Volume envelopeVol = dd4hep::xml::createPlacedEnvelope(theDetector, e , sdet) ; diff --git a/detector/calorimeter/ECalEndcap_o1_v01_geo.cpp b/detector/calorimeter/ECalEndcap_o1_v01_geo.cpp index d78650fd6..f27941378 100644 --- a/detector/calorimeter/ECalEndcap_o1_v01_geo.cpp +++ b/detector/calorimeter/ECalEndcap_o1_v01_geo.cpp @@ -184,7 +184,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s // Loop over the sets of layer elements in the detector double check_thick = 0.0; int l_num = 1; - int l_set = 0; for(xml_coll_t li(x_det,_U(layer)); li; ++li) { xml_comp_t x_layer = li; @@ -281,7 +280,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s // Increment layer number ++l_num; } - l_set++; } std::cout << "Total slice thickness check " << check_thick << " cm" << std::endl; diff --git a/detector/calorimeter/GenericCalBarrel_o1_v01_geo.cpp b/detector/calorimeter/GenericCalBarrel_o1_v01_geo.cpp index 3b199f76c..77a718c61 100644 --- a/detector/calorimeter/GenericCalBarrel_o1_v01_geo.cpp +++ b/detector/calorimeter/GenericCalBarrel_o1_v01_geo.cpp @@ -74,8 +74,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s string det_type = x_det.typeStr(); Material air = theDetector.air(); double totalThickness = layering.totalThickness(); - int totalRepeat = 0; - int totalSlices = 0; double gap = xml_dim_t(x_det).gap(); int nsides = dim.numsides(); @@ -110,14 +108,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s caloData->gap1 = 0.; //FIXME caloData->gap2 = 0.; //FIXME - - for (xml_coll_t c(x_det, _U(layer)); c; ++c) { - xml_comp_t x_layer = c; - int repeat = x_layer.repeat(); - totalRepeat += repeat; - totalSlices += x_layer.numChildren(_U(slice)); - } - // --- create an envelope volume and position it into the world --------------------- Volume envelopeVol = dd4hep::xml::createPlacedEnvelope( theDetector, e , sdet ) ; diff --git a/detector/calorimeter/HCalBarrel_o1_v01_geo.cpp b/detector/calorimeter/HCalBarrel_o1_v01_geo.cpp index dbee8243b..060606e5b 100644 --- a/detector/calorimeter/HCalBarrel_o1_v01_geo.cpp +++ b/detector/calorimeter/HCalBarrel_o1_v01_geo.cpp @@ -22,7 +22,7 @@ using dd4hep::Layer; using dd4hep::Layering; using dd4hep::Material; using dd4hep::PlacedVolume; -using dd4hep::PolyhedraRegular; +// using dd4hep::PolyhedraRegular; using dd4hep::Position; using dd4hep::Readout; using dd4hep::Ref_t; @@ -70,8 +70,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s string det_type = x_det.typeStr(); Material air = theDetector.air(); double totalThickness = layering.totalThickness(); - int totalRepeat = 0; - int totalSlices = 0; double gap = xml_dim_t(x_det).gap(); int nsides = dim.numsides(); @@ -106,14 +104,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s caloData->gap1 = 0.; //FIXME caloData->gap2 = 0.; //FIXME - - for (xml_coll_t c(x_det, _U(layer)); c; ++c) { - xml_comp_t x_layer = c; - int repeat = x_layer.repeat(); - totalRepeat += repeat; - totalSlices += x_layer.numChildren(_U(slice)); - } - // --- create an envelope volume and position it into the world --------------------- Volume envelopeVol = dd4hep::xml::createPlacedEnvelope( theDetector, e , sdet ) ; diff --git a/detector/calorimeter/HCalThreePartsEndcap_o1_v01_geo.cpp b/detector/calorimeter/HCalThreePartsEndcap_o1_v01_geo.cpp index e02d4bfea..34544c2e2 100644 --- a/detector/calorimeter/HCalThreePartsEndcap_o1_v01_geo.cpp +++ b/detector/calorimeter/HCalThreePartsEndcap_o1_v01_geo.cpp @@ -5,7 +5,6 @@ #define endmsg std::endl #define lLog std::cout namespace MSG { -const std::string ERROR = " Error: "; const std::string DEBUG = " Debug: "; const std::string INFO = " Info: "; } @@ -216,7 +215,6 @@ void buildEC(dd4hep::Detector& aLcdd, dd4hep::SensitiveDetector& aSensDet, dd4he layerVolume.setVisAttributes(aLcdd.invisible()); unsigned int idxSubMod = 0; - unsigned int idxActMod = 0; dd4hep::Position moduleOffset1 (0,0,sign * extBarrelOffset1); @@ -248,7 +246,6 @@ void buildEC(dd4hep::Detector& aLcdd, dd4hep::SensitiveDetector& aSensDet, dd4he if (xComp.isSensitive()) { tileVol.setSensitiveDetector(sensDet); tilesPerLayer.push_back(placedTileVol); - idxActMod++; } tileZOffset += xComp.thickness(); } @@ -290,7 +287,6 @@ void buildEC(dd4hep::Detector& aLcdd, dd4hep::SensitiveDetector& aSensDet, dd4he layerVolume.setVisAttributes(aLcdd.invisible()); unsigned int idxSubMod = 0; - unsigned int idxActMod = 0; double tileZOffset = - 0.5* dzSequence; @@ -311,7 +307,6 @@ void buildEC(dd4hep::Detector& aLcdd, dd4hep::SensitiveDetector& aSensDet, dd4he if (xComp.isSensitive()) { tileVol.setSensitiveDetector(sensDet); tilesPerLayer.push_back(placedTileVol); - idxActMod++; } tileZOffset += xComp.thickness(); } @@ -361,7 +356,6 @@ void buildEC(dd4hep::Detector& aLcdd, dd4hep::SensitiveDetector& aSensDet, dd4he layerVolume.setVisAttributes(aLcdd.invisible()); unsigned int idxSubMod = 0; - unsigned int idxActMod = 0; double tileZOffset = - 0.5* dzSequence; @@ -382,7 +376,6 @@ void buildEC(dd4hep::Detector& aLcdd, dd4hep::SensitiveDetector& aSensDet, dd4he if (xComp.isSensitive()) { tileVol.setSensitiveDetector(sensDet); tilesPerLayer.push_back(placedTileVol); - idxActMod++; } tileZOffset += xComp.thickness(); } diff --git a/detector/calorimeter/HCalTileBarrel_o1_v01_geo.cpp b/detector/calorimeter/HCalTileBarrel_o1_v01_geo.cpp index e6d67caa8..89be7154d 100644 --- a/detector/calorimeter/HCalTileBarrel_o1_v01_geo.cpp +++ b/detector/calorimeter/HCalTileBarrel_o1_v01_geo.cpp @@ -12,7 +12,6 @@ using dd4hep::PlacedVolume; #define endmsg std::endl #define lLog std::cout namespace MSG { -const std::string ERROR = " Error: "; const std::string DEBUG = " Debug: "; const std::string INFO = " Info: "; } @@ -168,7 +167,6 @@ static dd4hep::Ref_t createHCal(dd4hep::Detector& lcdd, xml_det_t xmlDet, dd4hep layerVolume.setVisAttributes(lcdd.invisible()); unsigned int idxSubMod = 0; - unsigned int idxActMod = 0; dd4hep::PlacedVolume placedLayerVolume = envelopeVolume.placeVolume(layerVolume); @@ -192,7 +190,6 @@ static dd4hep::Ref_t createHCal(dd4hep::Detector& lcdd, xml_det_t xmlDet, dd4hep if (xComp.isSensitive()) { tileVol.setSensitiveDetector(sensDet); tilesPerLayer.push_back(placedTileVol); - idxActMod++; } tileZOffset += xComp.thickness(); } diff --git a/detector/calorimeter/SECalEndcap_o1_v01_geo.cpp b/detector/calorimeter/SECalEndcap_o1_v01_geo.cpp index 338282826..bf16d0348 100644 --- a/detector/calorimeter/SECalEndcap_o1_v01_geo.cpp +++ b/detector/calorimeter/SECalEndcap_o1_v01_geo.cpp @@ -193,7 +193,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s // Loop over the sets of layer elements in the detector double check_thick = 0.0; int l_num = 1; - int l_set = 0; for(xml_coll_t li(x_det,_U(layer)); li; ++li) { xml_comp_t x_layer = li; @@ -289,7 +288,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s // Increment layer number ++l_num; } - l_set++; } std::cout << "Total slice thickness check " << check_thick << " cm" << std::endl; diff --git a/detector/calorimeter/SEcal05_ECRing.cpp b/detector/calorimeter/SEcal05_ECRing.cpp index aee2e0b16..186ad7605 100644 --- a/detector/calorimeter/SEcal05_ECRing.cpp +++ b/detector/calorimeter/SEcal05_ECRing.cpp @@ -210,7 +210,7 @@ static Ref_t create_detector(Detector& theDetector, xml_h element, SensitiveDete // //==================================================================== - int Number_of_Si_Layers_in_Barrel = 0; + int Number_of_Si_Layers_in_Barrel [[maybe_unused]] = 0; #ifdef VERBOSE std::cout << " Ecal total number of Silicon layers = " << Number_of_Si_Layers_in_Barrel << std::endl; diff --git a/detector/calorimeter/SteppedMuonBarrel_o2_v02_geo.cpp b/detector/calorimeter/SteppedMuonBarrel_o2_v02_geo.cpp index 11df5cee7..0d8e42da6 100644 --- a/detector/calorimeter/SteppedMuonBarrel_o2_v02_geo.cpp +++ b/detector/calorimeter/SteppedMuonBarrel_o2_v02_geo.cpp @@ -52,8 +52,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s string det_type = x_det.typeStr(); Material air = theDetector.air(); double totalThickness = layering.totalThickness(); - int totalRepeat = 0; - int totalSlices = 0; double gap = xml_dim_t(x_det).gap(); int nsides = dim.numsides(); @@ -93,13 +91,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s caloData->gap1 = 0.; //FIXME caloData->gap2 = 0.; //FIXME - for (xml_coll_t c(x_det, _U(layer)); c; ++c) { - xml_comp_t x_layer = c; - int repeat = x_layer.repeat(); - totalRepeat += repeat; - totalSlices += x_layer.numChildren(_U(slice)); - } - // CHECK THIS! // --- create an envelope volume and position it into the world --------------------- diff --git a/detector/calorimeter/YokeBarrel_o1_v01_geo.cpp b/detector/calorimeter/YokeBarrel_o1_v01_geo.cpp index 673a5dd63..5be170b91 100644 --- a/detector/calorimeter/YokeBarrel_o1_v01_geo.cpp +++ b/detector/calorimeter/YokeBarrel_o1_v01_geo.cpp @@ -22,7 +22,7 @@ using dd4hep::Layer; using dd4hep::Layering; using dd4hep::Material; using dd4hep::PlacedVolume; -using dd4hep::PolyhedraRegular; +// using dd4hep::PolyhedraRegular; using dd4hep::Position; using dd4hep::Readout; using dd4hep::Ref_t; @@ -70,8 +70,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s string det_type = x_det.typeStr(); Material air = theDetector.air(); double totalThickness = layering.totalThickness(); - int totalRepeat = 0; - int totalSlices = 0; double gap = xml_dim_t(x_det).gap(); int numSides = dim.numsides(); double detZ = dim.z(); @@ -98,14 +96,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s caloData->gap1 = 0.; //FIXME caloData->gap2 = 0.; //FIXME - - for (xml_coll_t c(x_det, _U(layer)); c; ++c) { - xml_comp_t x_layer = c; - int repeat = x_layer.repeat(); - totalRepeat += repeat; - totalSlices += x_layer.numChildren(_U(slice)); - } - // --- create an envelope volume and position it into the world --------------------- Volume envelopeVol = dd4hep::xml::createPlacedEnvelope( theDetector, e , sdet ) ; diff --git a/detector/calorimeter/YokeEndcap_o1_v01_geo.cpp b/detector/calorimeter/YokeEndcap_o1_v01_geo.cpp index 169ee3082..2f957424c 100644 --- a/detector/calorimeter/YokeEndcap_o1_v01_geo.cpp +++ b/detector/calorimeter/YokeEndcap_o1_v01_geo.cpp @@ -20,7 +20,6 @@ using dd4hep::RotationZYX; using dd4hep::Segmentation; using dd4hep::SensitiveDetector; using dd4hep::Transform3D; -using dd4hep::Tube; using dd4hep::Volume; using dd4hep::_toString; @@ -114,7 +113,6 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s double sliceZ = -l_thick/2; double totalAbsorberThickness=0.; - double th_i(0.), th_o(-1.) ; for(xml_coll_t s(x_layer,_U(slice)); s; ++s) { xml_comp_t x_slice = s; string s_name = _toString(s_num,"slice%d"); @@ -132,15 +130,7 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s s_phv.addPhysVolID("submodule",sensor_num); sensor_num++; - th_i += s_thick / 2. ; - th_o = s_thick / 2. ; - } else { - if( th_o < 0. ){ - th_i += s_thick; - } else { - th_o += s_thick; - } - } + } if( x_slice.isRadiator() ==true) totalAbsorberThickness+= s_thick; diff --git a/detector/tracker/VertexBarrel_detailed_o1_v01_geo.cpp b/detector/tracker/VertexBarrel_detailed_o1_v01_geo.cpp index 9ade326c0..cc9704eb5 100644 --- a/detector/tracker/VertexBarrel_detailed_o1_v01_geo.cpp +++ b/detector/tracker/VertexBarrel_detailed_o1_v01_geo.cpp @@ -43,10 +43,10 @@ using dd4hep::Translation3D; using dd4hep::Trapezoid; using dd4hep::Volume; using dd4hep::_toString; -using dd4hep::rec::Vector3D; -using dd4hep::rec::SurfaceType; +// using dd4hep::rec::Vector3D; +// using dd4hep::rec::SurfaceType; using dd4hep::rec::VolPlane; -using dd4hep::rec::volSurfaceList; +// using dd4hep::rec::volSurfaceList; static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector sens) { @@ -55,7 +55,7 @@ static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector se std::string det_name = x_det.nameStr(); DetElement sdet( det_name, x_det.id() ) ; - PlacedVolume pv; + // PlacedVolume pv; // put the whole detector into an assembly // - should be replaced by an envelope volume ... @@ -182,7 +182,8 @@ static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector se m.sensor_thickness = xml_comp_t(c_sensor).thickness(); xml_coll_t c_component = xml_coll_t(c_sensor,_U(component)); - int iSensitive, iPassive = 0; + // Is iSensitive being used later with this default value in a call to _toString? + int iSensitive = 0, iPassive = 0; for(c_component.reset(); c_component; ++c_component){ xml_comp_t component = c_component; m.sensor_sensitives.push_back(component.isSensitive()); @@ -341,7 +342,7 @@ static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector se // passivesDE.setPlacement(pv); // Place all sensor parts - int iSensitive = 0, iPassive = 0; + int iSensitive = 0; for(int i=0; i Date: Mon, 26 Feb 2024 08:02:49 +0100 Subject: [PATCH 10/42] Update the key4hep-build workflow; previous commit: Clean up unused variables (#302) --- .github/workflows/downstream-build.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/downstream-build.yaml b/.github/workflows/downstream-build.yaml index e763bb47a..df5bac57d 100644 --- a/.github/workflows/downstream-build.yaml +++ b/.github/workflows/downstream-build.yaml @@ -5,11 +5,10 @@ on: workflow_dispatch: jobs: - test: + downstream-build: runs-on: ubuntu-latest strategy: fail-fast: false steps: - - uses: actions/checkout@v3 - - uses: cvmfs-contrib/github-action-cvmfs@v3 + - uses: actions/checkout@v4 - uses: key4hep/key4hep-actions/downstream-build@main From 1122f7de9537e58612d5bef62a4369b2ceff774c Mon Sep 17 00:00:00 2001 From: Anna Date: Wed, 6 Mar 2024 11:00:27 +0100 Subject: [PATCH 11/42] Make LCIO an optional dependency (#328) --- CMakeLists.txt | 55 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e2c52bc7..d1441d0b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,20 +51,20 @@ find_package ( ROOT REQUIRED COMPONENTS Geom GenVector) message ( STATUS "ROOT_VERSION: ${ROOT_VERSION}" ) find_package( Geant4 REQUIRED ) -find_package( LCIO REQUIRED) -# Shim for older LCIO versions -if(NOT TARGET LCIO::lcio) - add_library(LCIO::lcio INTERFACE IMPORTED GLOBAL) - set_target_properties(LCIO::lcio - PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${LCIO_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES "${LCIO_LIBRARIES}" - ) +OPTION(K4GEO_USE_LCIO "Enable or disable the use of LCIO, which is needed for some detector constructors and plugins" ON) +if(K4GEO_USE_LCIO) + find_package(LCIO REQUIRED) + # Shim for older LCIO versions + if(NOT TARGET LCIO::lcio) + add_library(LCIO::lcio INTERFACE IMPORTED GLOBAL) + set_target_properties(LCIO::lcio + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${LCIO_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${LCIO_LIBRARIES}" + ) + endif() endif() -add_subdirectory(detectorSegmentations) -add_subdirectory(detectorCommon) - file(GLOB sources ./detector/tracker/*.cpp ./detector/calorimeter/*.cpp @@ -76,6 +76,25 @@ file(GLOB sources ./detector/PID/ARC_geo_o1_v01.cpp ) +if(NOT K4GEO_USE_LCIO) + set(lcio_sources # in ./detector/tracker + TrackerEndcap_o2_v05_geo.cpp + SiTrackerEndcap_o2_v02ext_geo.cpp + TrackerBarrel_o1_v03_geo.cpp + TrackerBarrel_o1_v04_geo.cpp + TrackerBarrel_o1_v05_geo.cpp + TrackerEndcap_o1_v05_geo.cpp + TrackerEndcap_o2_v06_geo.cpp + VertexBarrel_detailed_o1_v01_geo.cpp + VertexEndcap_o1_v05_geo.cpp + ZPlanarTracker_geo.cpp + ) + foreach(lcio_source ${lcio_sources}) + list(FILTER sources EXCLUDE REGEX "${lcio_source}") + endforeach() + message(STATUS "Use of LCIO is DISABLED, some detectors that depend on LCIO will not be built: ${lcio_sources}") +endif() + file(GLOB G4sources ./plugins/TPCSDAction.cpp ./plugins/CaloPreShowerSDAction.cpp @@ -94,12 +113,20 @@ add_library(lcgeo ALIAS k4geo) target_include_directories(${PackageName} PRIVATE ${PROJECT_SOURCE_DIR}/detector/include ) target_include_directories(${PackageName}G4 PRIVATE ${PROJECT_SOURCE_DIR}/detector/include ) -target_link_libraries(${PackageName} DD4hep::DDCore DD4hep::DDRec DD4hep::DDParsers ROOT::Core LCIO::lcio detectorSegmentations) -target_link_libraries(${PackageName}G4 DD4hep::DDCore DD4hep::DDRec DD4hep::DDParsers DD4hep::DDG4 ROOT::Core ${Geant4_LIBRARIES} LCIO::lcio) +target_link_libraries(${PackageName} DD4hep::DDCore DD4hep::DDRec DD4hep::DDParsers ROOT::Core detectorSegmentations) +target_link_libraries(${PackageName}G4 DD4hep::DDCore DD4hep::DDRec DD4hep::DDParsers DD4hep::DDG4 ROOT::Core ${Geant4_LIBRARIES}) + +if(K4GEO_USE_LCIO) + target_link_libraries(${PackageName} LCIO::lcio) + target_link_libraries(${PackageName}G4 LCIO::lcio) +endif() #Create this_package.sh file, and install dd4hep_instantiate_package(${PackageName}) +add_subdirectory(detectorSegmentations) +add_subdirectory(detectorCommon) + # Destination directories are hardcoded because GNUdirectories are not included install(TARGETS ${PackageName} ${PackageName}G4 EXPORT ${PROJECT_NAME}Targets From 89955b056bd4bc86c572f16ed168977e5f6aa86d Mon Sep 17 00:00:00 2001 From: Brieuc Francois Date: Thu, 21 Mar 2024 11:55:00 +0100 Subject: [PATCH 12/42] Add CLD_o4_v05 description in FCCee README (#329) --- FCCee/CLD/compact/README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/FCCee/CLD/compact/README.md b/FCCee/CLD/compact/README.md index ea10994bf..7dfa17656 100644 --- a/FCCee/CLD/compact/README.md +++ b/FCCee/CLD/compact/README.md @@ -37,4 +37,9 @@ Overlaps in the Inner and Outer Tracker. CLD_o3_v01 ---------- -This model is based on CLD_o2_v05. The tracker size is reduced to accomodate the ARC detector for PID. \ No newline at end of file +This model is based on CLD_o2_v05. The tracker size is reduced to accomodate the ARC detector for PID. + +CLD_o4_v05 +---------- + +This model is based on CLD_o2_v05. The ECAL barrel is replaced by the Noble Liquid calorimeter from ALLEGRO to enable PandoraPFA technical developments. To accomodate the thicker ALLEGRO calorimeter, the CLD detectors after ECAL were pushed towards higher radius. From 3bc0d8108b49a541e8f46b24da2dc72c32da3d79 Mon Sep 17 00:00:00 2001 From: Brieuc Francois Date: Thu, 21 Mar 2024 21:58:27 +0100 Subject: [PATCH 13/42] [IDEA] Add a solenoid and magnetic fields (#327) --- .../DectDimensions_IDEA_o1_v01.xml | 18 ++++--- .../IDEA_o1_v02/EndPlateAbsorber_o1_v01.xml | 21 ++++++++ .../IDEA/compact/IDEA_o1_v02/IDEA_o1_v02.xml | 32 ++++++++++++ .../compact/IDEA_o1_v02/Solenoid_o1_v01.xml | 50 +++++++++++++++++++ FCCee/IDEA/compact/README.md | 2 +- 5 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 FCCee/IDEA/compact/IDEA_o1_v02/EndPlateAbsorber_o1_v01.xml create mode 100644 FCCee/IDEA/compact/IDEA_o1_v02/Solenoid_o1_v01.xml diff --git a/FCCee/IDEA/compact/IDEA_o1_v02/DectDimensions_IDEA_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v02/DectDimensions_IDEA_o1_v01.xml index 27a5bb4fc..90dc7d53a 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v02/DectDimensions_IDEA_o1_v01.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v02/DectDimensions_IDEA_o1_v01.xml @@ -92,6 +92,18 @@ + + + + + + + + + + + + @@ -131,12 +143,6 @@ - - - - - - diff --git a/FCCee/IDEA/compact/IDEA_o1_v02/EndPlateAbsorber_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v02/EndPlateAbsorber_o1_v01.xml new file mode 100644 index 000000000..55acb6c6d --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v02/EndPlateAbsorber_o1_v01.xml @@ -0,0 +1,21 @@ + + + + + Endcap plate absorber to mimic the material budget from the solenoid (0.75 X0) present only in the barrel and start the showers. + + + + + + + + + + + + + + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v02/IDEA_o1_v02.xml b/FCCee/IDEA/compact/IDEA_o1_v02/IDEA_o1_v02.xml index 5ea3592ad..4619c7cfb 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v02/IDEA_o1_v02.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v02/IDEA_o1_v02.xml @@ -47,9 +47,41 @@ + + + + + + + + + + + + + + + + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v02/Solenoid_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v02/Solenoid_o1_v01.xml new file mode 100644 index 000000000..7287662e0 --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v02/Solenoid_o1_v01.xml @@ -0,0 +1,50 @@ + + + + This is a solenoid place holder. It has the right spacial extent and overall accounts for the 0.75 X0 but its internals should be revised by ultra-thin magnet designers --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/IDEA/compact/README.md b/FCCee/IDEA/compact/README.md index 532f3335f..17ba793c0 100644 --- a/FCCee/IDEA/compact/README.md +++ b/FCCee/IDEA/compact/README.md @@ -1,4 +1,4 @@ IDEA ==== IDEA_o1_v01: IDEA version picked from the latest version in FCCDetectors repo -IDEA_o1_v02: Based on o1_v01 but with a detailed description of the vertex detector and the drift chamber +IDEA_o1_v02: Based on o1_v01 but with a detailed description of the vertex detector and the drift chamber, a place holder solenoid and the endplate absorber. Missing: SiWrapper, calorimeter, detailed muons system (coming soon). From 527680d83d35bc1d94cc1a46a919ffeb773a4a7d Mon Sep 17 00:00:00 2001 From: BrieucF Date: Thu, 29 Feb 2024 17:25:15 +0100 Subject: [PATCH 14/42] README: Correct description for CLD_o2_v06 --- FCCee/CLD/compact/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/FCCee/CLD/compact/README.md b/FCCee/CLD/compact/README.md index 7dfa17656..0db117277 100644 --- a/FCCee/CLD/compact/README.md +++ b/FCCee/CLD/compact/README.md @@ -33,6 +33,10 @@ This model is based on `FCCee_o2_v02` from k4geo. It has an updated design of th standard design (low-impedance, no HOM absorber); changed Vertex Detector Barrel layers to fit the beampipe contraints (reduced barrel length); fixed Overlaps in the Inner and Outer Tracker. +CLD_o2_v06 +---------- + +This model is based on `CLD_o2_v05` with the following changes: LumiCal outer radius from 112 mm to 115 mm, define its z extent in the beampipe reference frame. CLD_o3_v01 ---------- From f61ba941a56f47444543a7558388faaaf2ff2629 Mon Sep 17 00:00:00 2001 From: BrieucF Date: Thu, 29 Feb 2024 17:16:28 +0100 Subject: [PATCH 15/42] CLD_o2_v06: Start with new detector model --- .../BeamInstrumentation_o3_v02_fitShield.xml | 26 + .../compact/CLD_o2_v06/Beampipe_o4_v05.xml | 158 ++++ FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml | 437 +++++++++ .../CLD_o2_v06/ECalBarrel_o2_v01_03.xml | 66 ++ .../CLD_o2_v06/ECalEndcap_o2_v01_03.xml | 57 ++ .../CLD_o2_v06/HCalBarrel_o1_v01_01.xml | 58 ++ .../CLD_o2_v06/HCalEndcap_o1_v01_01.xml | 131 +++ .../InnerTrackerBarrelModuleDown.xml | 25 + .../CLD_o2_v06/InnerTrackerBarrelModuleUp.xml | 25 + .../CLD_o2_v06/InnerTracker_o2_v07.xml | 582 ++++++++++++ .../compact/CLD_o2_v06/LumiCal_o3_v02_04.xml | 180 ++++ .../OuterTrackerBarrelModuleDown.xml | 27 + .../CLD_o2_v06/OuterTrackerBarrelModuleUp.xml | 27 + .../CLD_o2_v06/OuterTracker_o2_v07.xml | 226 +++++ .../compact/CLD_o2_v06/Solenoid_o1_v01_02.xml | 54 ++ .../CLD_o2_v06/TrackerDiskModuleIn.xml | 27 + .../CLD_o2_v06/TrackerDiskModuleOut.xml | 27 + .../CLD_o2_v06/Vertex_o4_v07_smallBP.xml | 225 +++++ .../CLD_o2_v06/YokeBarrel_o1_v01_02.xml | 68 ++ .../CLD_o2_v06/YokeEndcap_o1_v01_02.xml | 67 ++ FCCee/CLD/compact/CLD_o2_v06/elements.xml | 884 ++++++++++++++++++ FCCee/CLD/compact/CLD_o2_v06/materials.xml | 230 +++++ FCCee/CLD/compact/README.md | 2 +- 23 files changed, 3608 insertions(+), 1 deletion(-) create mode 100644 FCCee/CLD/compact/CLD_o2_v06/BeamInstrumentation_o3_v02_fitShield.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/Beampipe_o4_v05.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/ECalBarrel_o2_v01_03.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/ECalEndcap_o2_v01_03.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/HCalBarrel_o1_v01_01.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/HCalEndcap_o1_v01_01.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/InnerTrackerBarrelModuleDown.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/InnerTrackerBarrelModuleUp.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/InnerTracker_o2_v07.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/LumiCal_o3_v02_04.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/OuterTrackerBarrelModuleDown.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/OuterTrackerBarrelModuleUp.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/OuterTracker_o2_v07.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/Solenoid_o1_v01_02.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/TrackerDiskModuleIn.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/TrackerDiskModuleOut.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/Vertex_o4_v07_smallBP.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/YokeBarrel_o1_v01_02.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/YokeEndcap_o1_v01_02.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/elements.xml create mode 100644 FCCee/CLD/compact/CLD_o2_v06/materials.xml diff --git a/FCCee/CLD/compact/CLD_o2_v06/BeamInstrumentation_o3_v02_fitShield.xml b/FCCee/CLD/compact/CLD_o2_v06/BeamInstrumentation_o3_v02_fitShield.xml new file mode 100644 index 000000000..dba09d325 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/BeamInstrumentation_o3_v02_fitShield.xml @@ -0,0 +1,26 @@ + + + + Beampipe Instrumentation + + + + + + +
+ + + + + + + + +
+ +
+ + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/Beampipe_o4_v05.xml b/FCCee/CLD/compact/CLD_o2_v06/Beampipe_o4_v05.xml new file mode 100644 index 000000000..5610b7225 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/Beampipe_o4_v05.xml @@ -0,0 +1,158 @@ + + + + A beampipe for FCCee detector based on CLD + + + + + + + + + + + + + + + + + + + + + Part of beampipe made of AlBeMet162 and Paraffin flow + + + + + + + +
+
+
+
+ + + + + + + + + + + + Golden foil in the inner part of the Be beampipe + +
+ +
+ +
+ +
+ + +
+ +
+ +
+ +
+ +
+ + + + + +Synch Radiation mask inside the beam-pipe, at z = 2.1 m + + + +
+ +
+ +
+ + + +Full Cone Tungsten Shield + + + + Beampipe Shield (APS: WHAT????? +18 cm (??plus??) as solenoid is now closer to IP) +
+ + + + +Asymmetric Tungsten Shield no Rotation + + + + +
+ + was 370. Add 0.1*mm so that rmax1 is larger than rmin1 +
+ + one degree less, to fit lumical window +
+ +
+ + + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml b/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml new file mode 100644 index 000000000..33814f448 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml @@ -0,0 +1,437 @@ + + + + The compact format for the FCCee Detector design + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + suggested naming convention: + + main parameters: + + DET_inner_radius : inner radius of tube like envelope ( inscribed cylinder ) + DET_outer_radius : outer radius of tube like envelope ( circumscribed cylinder ) + DET_half_length : half length along z axis + DET_min_z : smallest absolute value on z-axis + DET_max_z : largest absolute value on z-axis + DET_inner_symmetry : number of sides on the inside ( 0 for tube ) + DET_outer_symmetry : number of sides on the inside ( 0 for tube ) + DET_inner_phi0 : optional rotation of the inner polygon ( in r-phi plane ) + DET_outer_phi0 : optional rotation of the outer polygon ( in r-phi plane ) + + additional parameters for cutting away volumes/shapes use one of the above with a number + appended and/or an extra specifiaction such as cone ( for a cut away cone ) + + DET_inner_radius_1 + DET_outer_radius_2 + DET_cone_min_z + DET_cone_max_z + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/ECalBarrel_o2_v01_03.xml b/FCCee/CLD/compact/CLD_o2_v06/ECalBarrel_o2_v01_03.xml new file mode 100644 index 000000000..abe72e0fa --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/ECalBarrel_o2_v01_03.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + system:5,side:2,module:8,stave:4,layer:9,submodule:4,x:32:-16,y:-16 + + + + + + + + + + + + + + + + + + EM Calorimeter Barrel + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/ECalEndcap_o2_v01_03.xml b/FCCee/CLD/compact/CLD_o2_v06/ECalEndcap_o2_v01_03.xml new file mode 100644 index 000000000..dd84c505f --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/ECalEndcap_o2_v01_03.xml @@ -0,0 +1,57 @@ + + + + + + + + + system:5,side:2,module:8,stave:4,layer:9,submodule:4,x:32:-16,y:-16 + + + + + + + + + Electromagnetic Calorimeter Endcap + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/HCalBarrel_o1_v01_01.xml b/FCCee/CLD/compact/CLD_o2_v06/HCalBarrel_o1_v01_01.xml new file mode 100644 index 000000000..d0ade5fc2 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/HCalBarrel_o1_v01_01.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + system:5,side:2,module:8,stave:4,layer:9,submodule:4,x:32:-16,y:-16 + + + + + + + Hadron Calorimeter Barrel + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/HCalEndcap_o1_v01_01.xml b/FCCee/CLD/compact/CLD_o2_v06/HCalEndcap_o1_v01_01.xml new file mode 100644 index 000000000..ef70e41e8 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/HCalEndcap_o1_v01_01.xml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + HCalEndcap Assembly + + + + + + + + + + + + + system:5,side:2,module:8,stave:4,layer:9,submodule:4,x:32:-16,y:-16 + + + + system:5,side:2,module:8,stave:4,layer:9,submodule:4,x:32:-16,y:-16 + + + + + + + + + Hadronic Calorimeter Endcap + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Hadronic Calorimeter Endcap + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/InnerTrackerBarrelModuleDown.xml b/FCCee/CLD/compact/CLD_o2_v06/InnerTrackerBarrelModuleDown.xml new file mode 100644 index 000000000..12d5d7485 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/InnerTrackerBarrelModuleDown.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FCCee/CLD/compact/CLD_o2_v06/InnerTrackerBarrelModuleUp.xml b/FCCee/CLD/compact/CLD_o2_v06/InnerTrackerBarrelModuleUp.xml new file mode 100644 index 000000000..a81418293 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/InnerTrackerBarrelModuleUp.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FCCee/CLD/compact/CLD_o2_v06/InnerTracker_o2_v07.xml b/FCCee/CLD/compact/CLD_o2_v06/InnerTracker_o2_v07.xml new file mode 100644 index 000000000..8406b1115 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/InnerTracker_o2_v07.xml @@ -0,0 +1,582 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tracking detectors + + + + + + + + + + + + + Inner Tracker Assembly + + + + + + + + + + + + + + + + + + + + + + + + + ${GlobalTrackerReadoutID} + + + ${GlobalTrackerReadoutID} + + + + + + + + + + Silicon Inner Tracker Barrel + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Silicon Inner Tracker Endcaps + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3.5959*cm = X0 for Carbon fibre + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + The next section is the cable for the vertex + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/LumiCal_o3_v02_04.xml b/FCCee/CLD/compact/CLD_o2_v06/LumiCal_o3_v02_04.xml new file mode 100644 index 000000000..2ba7b4051 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/LumiCal_o3_v02_04.xml @@ -0,0 +1,180 @@ + + + + + + + + + + system:8,barrel:3,layer:8,slice:8,r:32:-16,phi:-16 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/OuterTrackerBarrelModuleDown.xml b/FCCee/CLD/compact/CLD_o2_v06/OuterTrackerBarrelModuleDown.xml new file mode 100644 index 000000000..8c0303810 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/OuterTrackerBarrelModuleDown.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FCCee/CLD/compact/CLD_o2_v06/OuterTrackerBarrelModuleUp.xml b/FCCee/CLD/compact/CLD_o2_v06/OuterTrackerBarrelModuleUp.xml new file mode 100644 index 000000000..12a1efe2e --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/OuterTrackerBarrelModuleUp.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FCCee/CLD/compact/CLD_o2_v06/OuterTracker_o2_v07.xml b/FCCee/CLD/compact/CLD_o2_v06/OuterTracker_o2_v07.xml new file mode 100644 index 000000000..fb8e27d9b --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/OuterTracker_o2_v07.xml @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Tracking detectors + + + + + Outer Tracker Assembly + + + + + + + + + + + + + + + + + + + + ${GlobalTrackerReadoutID} + + + ${GlobalTrackerReadoutID} + + + + + + + + + + + Silicon Outer Tracker Barrel + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Silicon Outer Tracker Endcaps + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/Solenoid_o1_v01_02.xml b/FCCee/CLD/compact/CLD_o2_v06/Solenoid_o1_v01_02.xml new file mode 100644 index 000000000..634f3cab3 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/Solenoid_o1_v01_02.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + Solenoid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/TrackerDiskModuleIn.xml b/FCCee/CLD/compact/CLD_o2_v06/TrackerDiskModuleIn.xml new file mode 100644 index 000000000..12a1efe2e --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/TrackerDiskModuleIn.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FCCee/CLD/compact/CLD_o2_v06/TrackerDiskModuleOut.xml b/FCCee/CLD/compact/CLD_o2_v06/TrackerDiskModuleOut.xml new file mode 100644 index 000000000..8c0303810 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/TrackerDiskModuleOut.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FCCee/CLD/compact/CLD_o2_v06/Vertex_o4_v07_smallBP.xml b/FCCee/CLD/compact/CLD_o2_v06/Vertex_o4_v07_smallBP.xml new file mode 100644 index 000000000..8082039f9 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/Vertex_o4_v07_smallBP.xml @@ -0,0 +1,225 @@ + + + + + Tracking detectors + + + + + + + + + + + Vertex Assembly + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${GlobalTrackerReadoutID} + + + ${GlobalTrackerReadoutID} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Vertex Detector Endcaps + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/YokeBarrel_o1_v01_02.xml b/FCCee/CLD/compact/CLD_o2_v06/YokeBarrel_o1_v01_02.xml new file mode 100644 index 000000000..5d4e62d73 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/YokeBarrel_o1_v01_02.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + system:5,side:2,layer:9,module:8,stave:4,submodule:4,x:32:-16,y:-16 + + + + + + + + Yoke Calorimeter Barrel + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/YokeEndcap_o1_v01_02.xml b/FCCee/CLD/compact/CLD_o2_v06/YokeEndcap_o1_v01_02.xml new file mode 100644 index 000000000..e4503843b --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/YokeEndcap_o1_v01_02.xml @@ -0,0 +1,67 @@ + + + + + + + system:5,side:2,module:8,stave:4,layer:9,submodule:4,x:32:-16,y:-16 + + + + + + + + + + + + + + Encap Yoke + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/CLD/compact/CLD_o2_v06/elements.xml b/FCCee/CLD/compact/CLD_o2_v06/elements.xml new file mode 100644 index 000000000..8358bac36 --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/elements.xml @@ -0,0 +1,884 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FCCee/CLD/compact/CLD_o2_v06/materials.xml b/FCCee/CLD/compact/CLD_o2_v06/materials.xml new file mode 100644 index 000000000..acdb4a66a --- /dev/null +++ b/FCCee/CLD/compact/CLD_o2_v06/materials.xml @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + diff --git a/FCCee/CLD/compact/README.md b/FCCee/CLD/compact/README.md index 0db117277..3c118cad9 100644 --- a/FCCee/CLD/compact/README.md +++ b/FCCee/CLD/compact/README.md @@ -36,7 +36,7 @@ Overlaps in the Inner and Outer Tracker. CLD_o2_v06 ---------- -This model is based on `CLD_o2_v05` with the following changes: LumiCal outer radius from 112 mm to 115 mm, define its z extent in the beampipe reference frame. +This model is based on `CLD_o2_v05` with the following changes: LumiCal outer radius from 112 mm to 115 mm, remove its nose shield, define its z extent in the beampipe reference frame. CLD_o3_v01 ---------- From 971f1a91d93cf2f9f851dc93a7afa7744f68dc72 Mon Sep 17 00:00:00 2001 From: BrieucF Date: Thu, 29 Feb 2024 17:16:28 +0100 Subject: [PATCH 16/42] CLD_o1_v06: Modify the LumiCal parameters to place it at 1074 along the outgoing beam axis --- FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml | 24 ++++++++++--------- .../compact/CLD_o2_v06/LumiCal_o3_v02_04.xml | 8 +++++++ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml b/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml index 33814f448..4c811d044 100644 --- a/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml +++ b/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml @@ -195,13 +195,18 @@ - - + + + - + + + + + - - + + @@ -217,11 +222,8 @@ - - - - - + + @@ -291,7 +293,7 @@ - + diff --git a/FCCee/CLD/compact/CLD_o2_v06/LumiCal_o3_v02_04.xml b/FCCee/CLD/compact/CLD_o2_v06/LumiCal_o3_v02_04.xml index 2ba7b4051..cbc708e20 100644 --- a/FCCee/CLD/compact/CLD_o2_v06/LumiCal_o3_v02_04.xml +++ b/FCCee/CLD/compact/CLD_o2_v06/LumiCal_o3_v02_04.xml @@ -25,12 +25,14 @@ + + @@ -66,12 +68,14 @@ + + @@ -106,12 +110,14 @@ + + @@ -145,12 +151,14 @@ + + From 94859f6d566e78be422f3d54bb1e3226d7c9971a Mon Sep 17 00:00:00 2001 From: Andre Sailer Date: Fri, 1 Mar 2024 09:07:40 +0100 Subject: [PATCH 17/42] CLD_o2_v06: Actually write what was changed --- FCCee/CLD/compact/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/FCCee/CLD/compact/README.md b/FCCee/CLD/compact/README.md index 3c118cad9..58ba2329a 100644 --- a/FCCee/CLD/compact/README.md +++ b/FCCee/CLD/compact/README.md @@ -36,7 +36,8 @@ Overlaps in the Inner and Outer Tracker. CLD_o2_v06 ---------- -This model is based on `CLD_o2_v05` with the following changes: LumiCal outer radius from 112 mm to 115 mm, remove its nose shield, define its z extent in the beampipe reference frame. +This model is based on `CLD_o2_v05` with the following changes: LumiCal outer radius from 112 mm to 115 mm, remove its +nose shield, place it at 1074*mm along the beam-axis, instead of at 1074*mm in Z, move LumiCal by 100*micron CLD_o3_v01 ---------- From e9d69b523c74132461ef58a4ee76a2388e14071e Mon Sep 17 00:00:00 2001 From: Andre Sailer Date: Fri, 8 Mar 2024 13:56:43 +0100 Subject: [PATCH 18/42] CLD_o2_v06: Fix XML syntax errors, variable spelling Co-authored-by: Alvaro Tolosa Delgado <114166109+atolosadelgado@users.noreply.github.com> --- FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml b/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml index 4c811d044..853cd02d4 100644 --- a/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml +++ b/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml @@ -197,12 +197,12 @@ - + - + - + From 63b76b3b51497290afa274b00aa7f49eb9244208 Mon Sep 17 00:00:00 2001 From: Andre Sailer Date: Sun, 24 Mar 2024 09:33:10 +0100 Subject: [PATCH 19/42] Test: switch to latest CLD version for testing --- lcgeoTests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcgeoTests/CMakeLists.txt b/lcgeoTests/CMakeLists.txt index 5df4cfc31..bf13a7940 100644 --- a/lcgeoTests/CMakeLists.txt +++ b/lcgeoTests/CMakeLists.txt @@ -69,7 +69,7 @@ ADD_TEST( t_${test_name} "${CMAKE_INSTALL_PREFIX}/bin/run_test_${PackageName}.sh ddsim --compactFile=${CMAKE_CURRENT_SOURCE_DIR}/../FCCee/CLD/compact/FCCee_o1_v05/FCCee_o1_v05.xml --runType=batch -G -N=1 --outputFile=testFCCee_o1_v05.slcio ) SET_TESTS_PROPERTIES( t_${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "Exception;EXCEPTION;ERROR;Error" ) -SET( det_name "CLD_o2_v05" ) +SET( det_name "CLD_o2_v06" ) ADD_TEST( t_test_${det_name} "${CMAKE_INSTALL_PREFIX}/bin/run_test_${PackageName}.sh" ddsim --compactFile=${CMAKE_CURRENT_SOURCE_DIR}/../FCCee/CLD/compact/${det_name}/${det_name}.xml --runType=batch -G -N=1 --outputFile=test${det_name}.slcio ) SET_TESTS_PROPERTIES( t_test_${det_name} PROPERTIES FAIL_REGULAR_EXPRESSION "Exception;EXCEPTION;ERROR;Error" ) From 5557137a79ecf03e8c901fcc7242d5c4599d375b Mon Sep 17 00:00:00 2001 From: Andre Sailer Date: Sun, 24 Mar 2024 09:36:02 +0100 Subject: [PATCH 20/42] CLD_o2_v06: correct and clarify description of changes --- FCCee/CLD/compact/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FCCee/CLD/compact/README.md b/FCCee/CLD/compact/README.md index 58ba2329a..bcd254a15 100644 --- a/FCCee/CLD/compact/README.md +++ b/FCCee/CLD/compact/README.md @@ -36,8 +36,8 @@ Overlaps in the Inner and Outer Tracker. CLD_o2_v06 ---------- -This model is based on `CLD_o2_v05` with the following changes: LumiCal outer radius from 112 mm to 115 mm, remove its -nose shield, place it at 1074*mm along the beam-axis, instead of at 1074*mm in Z, move LumiCal by 100*micron +This model is based on `CLD_o2_v05` with the following changes: LumiCal outer radius from 112 mm to 115 mm, remove +unused nose shield parameters, place LumiCal at 1074*mm along the beam-axis, instead of at 1074*mm in Z, moves LumiCal by 100*micron. CLD_o3_v01 ---------- From 1e73911b09c6c85e3ae2844faba2781586248d1f Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori <39376142+giovannimarchiori@users.noreply.github.com> Date: Tue, 16 Apr 2024 11:56:18 +0200 Subject: [PATCH 21/42] version of ALLEGRO with ECAL barrel with cell corners projective in phi (#332) * implement version of ALLEGRO with ECAL barrel with cell corners projective in phi * Update FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03.xml * add test for ALLEGRO o1 v03 * fix README * improve the comments * add detector construction v03 * updade also other xml files for inclined ecal barrel v03. Improve comments in xml of v02. In cpp of v03 add check that electrode length in xml is consistent with calo r1 r2 and inclination angle * include units in cpp --------- Co-authored-by: Brieuc Francois --- .../ECalBarrel_thetamodulemerged.xml | 4 +- ...alBarrel_thetamodulemerged_calibration.xml | 6 +- .../ECalBarrel_thetamodulemerged_upstream.xml | 4 +- .../compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03.xml | 46 + .../ALLEGRO_o1_v03_ecalonly.xml | 36 + .../ALLEGRO_o1_v03_trackeronly.xml | 40 + .../ALLEGRO_o1_v03/BeamInstrumentation.xml | 36 + .../compact/ALLEGRO_o1_v03/Beampipe.xml | 150 +++ .../compact/ALLEGRO_o1_v03/DectDimensions.xml | 230 +++++ .../ALLEGRO_o1_v03/DectEmptyMaster.xml | 30 + .../compact/ALLEGRO_o1_v03/DriftChamber.xml | 110 +++ .../ECalBarrel_thetamodulemerged.xml | 165 ++++ ...alBarrel_thetamodulemerged_calibration.xml | 157 ++++ .../ECalBarrel_thetamodulemerged_upstream.xml | 157 ++++ .../ALLEGRO_o1_v03/ECalEndcaps_coneCryo.xml | 167 ++++ .../ALLEGRO_o1_v03/HCalBarrel_TileCal.xml | 133 +++ .../HCalEndcaps_ThreeParts_TileCal.xml | 141 +++ .../compact/ALLEGRO_o1_v03/HOMAbsorber.xml | 64 ++ .../compact/ALLEGRO_o1_v03/LumiCal.xml | 191 ++++ .../compact/ALLEGRO_o1_v03/MuonTagger.xml | 50 + .../ALLEGRO_o1_v03/Solenoid_o1_v01_02.xml | 57 ++ .../ALLEGRO/compact/ALLEGRO_o1_v03/Vertex.xml | 234 +++++ .../compact/ALLEGRO_o1_v03/elements.xml | 884 ++++++++++++++++++ .../compact/ALLEGRO_o1_v03/materials.xml | 365 ++++++++ FCCee/ALLEGRO/compact/README.md | 2 + ...leLiquid_InclinedTrapezoids_o1_v02_geo.cpp | 80 +- ...leLiquid_InclinedTrapezoids_o1_v03_geo.cpp | 697 ++++++++++++++ lcgeoTests/CMakeLists.txt | 7 + 28 files changed, 4222 insertions(+), 21 deletions(-) create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_ecalonly.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_trackeronly.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/BeamInstrumentation.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Beampipe.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DectDimensions.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DectEmptyMaster.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DriftChamber.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_calibration.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_upstream.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalEndcaps_coneCryo.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/HCalBarrel_TileCal.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/HCalEndcaps_ThreeParts_TileCal.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/HOMAbsorber.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/LumiCal.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/MuonTagger.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Solenoid_o1_v01_02.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Vertex.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/elements.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/materials.xml create mode 100644 detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v03_geo.cpp diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged.xml index 9cf284bf0..08276aa34 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged.xml @@ -141,7 +141,9 @@ - + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_calibration.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_calibration.xml index 027f20800..85d79aaa6 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_calibration.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_calibration.xml @@ -133,11 +133,13 @@ - + + + - \ No newline at end of file + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_upstream.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_upstream.xml index 962746659..e022dc2c1 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_upstream.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ECalBarrel_thetamodulemerged_upstream.xml @@ -133,7 +133,9 @@ - + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03.xml new file mode 100644 index 000000000..16a7139ef --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03.xml @@ -0,0 +1,46 @@ + + + + + + Master compact file describing the latest developments of the FCCee ALLEGRO detector concept. With respect to v02 it features an ECal barrel with 11 layers and cell corners projective along phi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_ecalonly.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_ecalonly.xml new file mode 100644 index 000000000..01add4188 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_ecalonly.xml @@ -0,0 +1,36 @@ + + + + + + Master compact file describing the latest developments of the FCCee ALLEGRO detector concept. + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_trackeronly.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_trackeronly.xml new file mode 100644 index 000000000..d1150548a --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_trackeronly.xml @@ -0,0 +1,40 @@ + + + + + + Master compact file describing the latest developments of the FCCee ALLEGRO detector concept. + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/BeamInstrumentation.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/BeamInstrumentation.xml new file mode 100644 index 000000000..49647b2b8 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/BeamInstrumentation.xml @@ -0,0 +1,36 @@ + + + + COmpensating and screening solenoids for FCCee + + + + + Beampipe Instrumentation + + + + + + +

+ + + + + + + + +
+ +
+ + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Beampipe.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Beampipe.xml new file mode 100644 index 000000000..b86af5217 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Beampipe.xml @@ -0,0 +1,150 @@ + + + + A beampipe for FCCee, R(central) = 1.5 cm + + + + + + + + + + + + + + + + + + + + Part of beampipe made of Beryllium + + + + + + + +
+ +
+ + + + + + + + + + + + + Golden foil in the inner part of the Be beampipe + +
+ +
+ + Part of beampipe made of Copper + +
+ + + + + +
+ + + +
+ + +
+ + +Full Cone Tungsten Shield + + + + Before HOM space +
+ + After HOM space (1197.5*m - 1298.7*mm) +18 cm as solenoid is now closer to IP +
+ + +Asymmetric Tungsten Shield no Rotation + + + + +
+ + was 370 +
+ + one degree less, to fit lumical window +
+ +
+ + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DectDimensions.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DectDimensions.xml new file mode 100644 index 000000000..237223204 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DectDimensions.xml @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DectEmptyMaster.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DectEmptyMaster.xml new file mode 100644 index 000000000..263dcce4d --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DectEmptyMaster.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + Use this one if you want to use official dimensions but only place one detector inside + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DriftChamber.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DriftChamber.xml new file mode 100644 index 000000000..b24fa784f --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DriftChamber.xml @@ -0,0 +1,110 @@ + + + + Detector description for the IDEA Drift Chamber. To understand the free parameters below, look e.g. at https://indico.cern.ch/event/932973/contributions/4041314/attachments/2139657/3664808/primavera_FCCworkshop_2020.pdf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system:4,superLayer:5,layer:5,phi:11,hitorigin:3,stereo:1,layerInCell:2 + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged.xml new file mode 100644 index 000000000..7a978c8d9 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged.xml @@ -0,0 +1,165 @@ + + + + + + Settings for the inclined EM calorimeter. + The barrel is filled with liquid argon. Passive material includes lead in the middle and steal on the outside, glued together. + Passive plates are inclined by a certain angle from the radial direction. + In between of two passive plates there is a readout. + Space between the plate and readout is of trapezoidal shape and filled with liquid argon. + Definition of sizes, visualization settings, readout and longitudinal segmentation are specified. + The geometrical parameters (tilt and plane lengths) are adjusted, based on EMBarrel_rmin/max, to yield 1536 modules and cell corners aligned in phi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system:4,cryo:1,type:3,subtype:3,layer:8,module:11,theta:10 + + + + + + system:4,cryo:1,type:3,subtype:3,layer:8,module:11,theta:10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_calibration.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_calibration.xml new file mode 100644 index 000000000..d36f28b06 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_calibration.xml @@ -0,0 +1,157 @@ + + + + + Settings for the inclined EM calorimeter. + The barrel is filled with liquid argon. Passive material includes lead in the middle and steal on the outside, glued together. + Passive plates are inclined by a certain angle from the radial direction. + In between of two passive plates there is a readout. + Space between the plate and readout is of trapezoidal shape and filled with liquid argon. + Definition of sizes, visualization settings, readout and longitudinal segmentation are specified. + The geometrical parameters (tilt and plane lengths) are adjusted, based on EMBarrel_rmin/max, to yield 1536 modules and cell corners aligned in phi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system:4,cryo:1,type:3,subtype:3,layer:8,module:11,theta:10 + + + + + + system:4,cryo:1,type:3,subtype:3,layer:8,module:11,theta:10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_upstream.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_upstream.xml new file mode 100644 index 000000000..bc37473bd --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_upstream.xml @@ -0,0 +1,157 @@ + + + + + Settings for the inclined EM calorimeter. + The barrel is filled with liquid argon. Passive material includes lead in the middle and steal on the outside, glued together. + Passive plates are inclined by a certain angle from the radial direction. + In between of two passive plates there is a readout. + Space between the plate and readout is of trapezoidal shape and filled with liquid argon. + Definition of sizes, visualization settings, readout and longitudinal segmentation are specified. + The geometrical parameters (tilt and plane lengths) are adjusted, based on EMBarrel_rmin/max, to yield 1536 modules and cell corners aligned in phi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system:4,cryo:1,type:3,subtype:3,layer:8,module:11,theta:10 + + + + + + system:4,cryo:1,type:3,subtype:3,layer:8,module:11,theta:10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalEndcaps_coneCryo.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalEndcaps_coneCryo.xml new file mode 100644 index 000000000..33abcf035 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalEndcaps_coneCryo.xml @@ -0,0 +1,167 @@ + + + + + + Liquid argon EM calorimeter endcap design. + Electromagnetic part (EMEC) includes lead+steel absorber. + Absorbers have shape of simple discs. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system:4,subsystem:1,type:3,subtype:3,layer:8,sublayer:8,eta:10,phi:10 + + + + system:4,subsystem:1,type:3,subtype:3,layer:8,eta:10,phi:10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/HCalBarrel_TileCal.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/HCalBarrel_TileCal.xml new file mode 100644 index 000000000..714fffbe1 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/HCalBarrel_TileCal.xml @@ -0,0 +1,133 @@ + + + + The first FCCee HCal layout based on ATLAS HCal, not optimised yet + 1. Nov 2022, J. Faltova: update material and radial segmentation for FCCee + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system:4,layer:5,row:9,theta:9,phi:10 + + + + system:4,layer:5,theta:9,phi:10 + + + + + system:4,layer:5,row:9,theta:0,phi:10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/HCalEndcaps_ThreeParts_TileCal.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/HCalEndcaps_ThreeParts_TileCal.xml new file mode 100644 index 000000000..c5cbe72a7 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/HCalEndcaps_ThreeParts_TileCal.xml @@ -0,0 +1,141 @@ + + + + HCal layout based on ATLAS HCal, with realistic longitudinal segmentation and steel support + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system:4,type:2,layer:5,row:9,eta:11,phi:10 + + + + system:4,type:2,layer:4,eta:11,phi:10 + + + + + system:4,type:2,layer:5,row:9,eta:10,phi:10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/HOMAbsorber.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/HOMAbsorber.xml new file mode 100644 index 000000000..862207eaf --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/HOMAbsorber.xml @@ -0,0 +1,64 @@ + + + + Higher mode absorber for FCCee + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/LumiCal.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/LumiCal.xml new file mode 100644 index 000000000..15f0434e8 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/LumiCal.xml @@ -0,0 +1,191 @@ + + + + LumiCal for FCCee detector based on CLD + + + + + + + + + + system:8,barrel:3,layer:8,slice:8,r:32:-16,phi:-16 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/MuonTagger.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/MuonTagger.xml new file mode 100644 index 000000000..79b0ed182 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/MuonTagger.xml @@ -0,0 +1,50 @@ + + + + + + Simple muon tagger - barrel and endcaps + + + + + + + + + + + system:4,subsystem:1,type:3,subtype:3,layer:8,sublayer:8,eta:10,phi:10 + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Solenoid_o1_v01_02.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Solenoid_o1_v01_02.xml new file mode 100644 index 000000000..69a117f86 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Solenoid_o1_v01_02.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + Solenoid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Vertex.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Vertex.xml new file mode 100644 index 000000000..a28449d6f --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Vertex.xml @@ -0,0 +1,234 @@ + + + + + + CLD Vertex Detector for FCCee + + + Tracking detectors + + + + + + + + + + + + Vertex Assembly + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${GlobalTrackerReadoutID} + + + ${GlobalTrackerReadoutID} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Vertex Detector Endcaps + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/elements.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/elements.xml new file mode 100644 index 000000000..f35eb3454 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/elements.xml @@ -0,0 +1,884 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/materials.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/materials.xml new file mode 100644 index 000000000..7fe008147 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/materials.xml @@ -0,0 +1,365 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/README.md b/FCCee/ALLEGRO/compact/README.md index aecc08265..94f9ac59c 100644 --- a/FCCee/ALLEGRO/compact/README.md +++ b/FCCee/ALLEGRO/compact/README.md @@ -5,3 +5,5 @@ ALLEGRO_o1_v01: it is a liquid Noble gas based detector. This version picked fro ALLEGRO_o1_v02: evolves from o1_v01, replacing the barrel ECAL and adding a detailed version drift chamber. This version has a constant cell size in theta for the ECAL barrel (instead of eta as in o1_v01) and now it is possible to have a different number of cells merged for each longitudinal layer. Known caveat: the drift chamber has a larger z extent than in the IDEA detector but the wire spacing was not re-optimized. It is ok software-wise but the currently implemented design is not fully compliant with R&D considerations, will need a new drift chamber layout from the detector concept team. + +ALLEGRO_o1_v03: with respect to v02 it features an ECal barrel with 11 layers and cell corners projective along phi diff --git a/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v02_geo.cpp b/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v02_geo.cpp index 9c2c27b2b..bdb269ed6 100644 --- a/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v02_geo.cpp +++ b/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v02_geo.cpp @@ -48,6 +48,7 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, std::string activeMaterial = active.materialStr(); double activeThickness = active.thickness(); + // Retrieve information about active/passive overlap dd4hep::xml::DetElement overlap = active.child(_Unicode(overlap)); double activePassiveOverlap = overlap.offset(); if (activePassiveOverlap < 0 || activePassiveOverlap > 0.5) { @@ -55,6 +56,8 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, lLog << MSG::ERROR << "Overlap between active and passive cannot be more than half of passive plane!" << endmsg; //todo: incidentSvc->fireIncident(Incident("ECalConstruction", "GeometryFailure")); } + + // Retrieve length of layers along electrode, rescaled to active barrel radial extent dd4hep::xml::DetElement layers = calo.child(_Unicode(layers)); uint numLayers = 0; std::vector layerHeight; @@ -68,6 +71,7 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, layersTotalHeight += layer.repeat() * layer.thickness(); } lLog << MSG::DEBUG << "Number of layers: " << numLayers << " total thickness " << layersTotalHeight << endmsg; + // The following code checks if the xml geometry file contains a constant defining // the number of layers the barrel. In that case, it makes the program abort // if the number of planes in the xml is different from the one calculated from @@ -86,13 +90,16 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, // todo: incidentSvc->fireIncident(Incident("ECalConstruction", "GeometryFailure")); // make the code crash (incidentSvc does not work) // Andre, Alvaro, assert replaced by exception - throw std::runtime_error("Incorrect number of layers (ECalBarrelNumLayers) in xml file!"); + throw std::runtime_error("Incorrect number of layers (ECalBarrelNumLayers) in xml file!"); } + // Retrieve information about the readout dd4hep::xml::DetElement readout = calo.child(_Unicode(readout)); std::string readoutMaterial = readout.materialStr(); double readoutThickness = readout.thickness(); + // Retrieve info about passive elements + // (glue, outer - typically steel, inner - typically Pb, and LAr in presampling layer) dd4hep::xml::DetElement passive = calo.child(_Unicode(passive)); dd4hep::xml::DetElement passiveInner = passive.child(_Unicode(inner)); dd4hep::xml::DetElement passiveInnerMax = passive.child(_Unicode(innerMax)); @@ -106,16 +113,18 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, double passiveOuterThickness = passiveOuter.thickness(); double passiveGlueThickness = passiveGlue.thickness(); double passiveThickness = passiveInnerThicknessMin + passiveOuterThickness + passiveGlueThickness; + // inclination angle double angle = passive.rotation().angle(); - + // Retrieve info about bath dd4hep::xml::DetElement bath = aXmlElement.child(_Unicode(bath)); dd4hep::xml::Dimension bathDim(bath.dimensions()); double bathRmin = bathDim.rmin(); double bathRmax = bathDim.rmax(); dd4hep::Tube bathOuterShape(bathRmin, bathRmax, caloDim.dz()); // make it 4 volumes + 5th for detector envelope dd4hep::Tube bathAndServicesOuterShape(cryoDim.rmin2(), cryoDim.rmax1(), caloDim.dz()); // make it 4 volumes + 5th for detector envelope + + // 1. Create cryostat if (cryoThicknessFront > 0) { - // 1. Create cryostat dd4hep::Tube cryoFrontShape(cryoDim.rmin1(), cryoDim.rmin2(), cryoDim.dz()); dd4hep::Tube cryoBackShape(cryoDim.rmax1(), cryoDim.rmax2(), cryoDim.dz()); dd4hep::Tube cryoSideOuterShape(cryoDim.rmin2(), cryoDim.rmax1(), cryoDim.dz()); @@ -178,7 +187,8 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, servicesFrontDetElem.setPlacement(servicesFrontPhysVol); dd4hep::DetElement servicesBackDetElem(caloDetElem, "services_back", 0); servicesBackDetElem.setPlacement(servicesBackPhysVol); - } + } + // 2. Create bath that is inside the cryostat and surrounds the detector // Bath is filled with active material -> but not sensitive dd4hep::Volume bathVol(activeMaterial + "_bath", bathOuterShape, aLcdd.material(activeMaterial)); @@ -197,9 +207,12 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, // 3.a. Create the passive planes, readout in between of 2 passive planes and the remaining space fill with active // material + ////////////////////////////// // PASSIVE PLANES ////////////////////////////// + + // passive volumes consist of inner part and two outer, joined by glue lLog << MSG::INFO << "passive inner material = " << passiveInnerMaterial << "\n" << " and outer material = " << passiveOuterMaterial << "\n" << " thickness of inner part at inner radius (cm) = " << passiveInnerThicknessMin << "\n" @@ -207,6 +220,8 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, << " thickness of outer part (cm) = " << passiveOuterThickness << "\n" << " thickness of total (cm) = " << passiveThickness << "\n" << " rotation angle = " << angle << endmsg; + + // calculate number of modules uint numPlanes = round(M_PI / asin((passiveThickness + activeThickness + readoutThickness) / (2. * caloDim.rmin() * cos(angle)))); @@ -236,7 +251,7 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, // todo: incidentSvc->fireIncident(Incident("ECalConstruction", "GeometryFailure")); // make the code crash (incidentSvc does not work) // Andre, Alvaro, assert replaced by exception - throw std::runtime_error("Incorrect number of planes (ECalBarrelNumPlanes) in xml file!"); + throw std::runtime_error("Incorrect number of planes (ECalBarrelNumPlanes) in xml file!"); } // Readout is in the middle between two passive planes double offsetPassivePhi = caloDim.offset() + dPhi / 2.; @@ -244,15 +259,28 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, lLog << MSG::INFO << "readout material = " << readoutMaterial << "\n" << " thickness of readout planes (cm) = " << readoutThickness << "\n number of readout layers = " << numLayers << endmsg; + + // min and max radius of active calorimeter volume, and its radial thickness double Rmin = caloDim.rmin(); double Rmax = caloDim.rmax(); double dR = Rmax - Rmin; + // electrode length, given inclination angle and min/max radius of the active calorimeter volume double planeLength = -Rmin * cos(angle) + sqrt(pow(Rmax, 2) - pow(Rmin * sin(angle), 2)); lLog << MSG::INFO << "thickness of calorimeter (cm) = " << dR << "\n" << " length of passive or readout planes (cm) = " << planeLength << endmsg; - - // fill the thickness in the boundary of each layer + // calculate the thickness of the passive material in each layer + // it's not constant in case of trapezoidal absorbers (passiveInnerThicknessMax != passiveInnerThicknessMin) + // the code calculates the (max) passive thickness per layer i.e. at Rout of layer + // rescaling by runningHeight / (Rmax - Rmin) + // GM : should be OK since both Rmax-Rmin and runningHeight are radial extents + // but shouldn't it be simpler to define layerHeight as the length along the electrode + // and here use as rescaling factor runningHeight / layersTotalHeight ? + // This is only place where the fact that the layer thicknesses in the xml are rescaled to + // the radial extent of the calo is used, because after this block of code the + // layer thicknesses are rescaled to the electrode length. + // So maybe we could implement in the xml the length along the electrode, and here + // rescale by runningHeight/Ltot where runningHeight is calculated along the electrode direction? std::vector passiveInnerThicknessLayer(numLayers+1); double runningHeight = 0; for (uint iLay = 0; iLay < numLayers; iLay++) { @@ -263,12 +291,15 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, passiveInnerThicknessLayer[numLayers] = passiveInnerThicknessMin + (passiveInnerThicknessMax - passiveInnerThicknessMin) * (runningHeight) / (Rmax - Rmin); + // calculate the angle of the passive elements if trapezoidal absorbers are used (Max != Min) + // if parallel absorbers are used then passiveAngle = 0 and cosPassiveAngle = 1 double passiveAngle = atan2((passiveInnerThicknessMax - passiveInnerThicknessMin) / 2., planeLength); double cosPassiveAngle = cos(passiveAngle); double rotatedOuterThickness = passiveOuterThickness / cosPassiveAngle; double rotatedGlueThickness = passiveGlueThickness / cosPassiveAngle; - // rescale layer thicknesses + // rescale layer thicknesses from xml so that they now represent the real + // lengths along the electrode direction double scaleLayerThickness = planeLength / layersTotalHeight; layersTotalHeight = 0; for (uint iLay = 0; iLay < numLayers; iLay++) { @@ -277,21 +308,26 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, layersTotalHeight += layerHeight[iLay]; lLog << MSG::DEBUG << "Thickness of layer " << iLay << " : " << layerHeight[iLay] << endmsg; } + + // distance from the center of the electrode to the center of the 1st layer, in the electrode direction double layerFirstOffset = -planeLength / 2. + layerHeight[0] / 2.; - //dd4hep::Box passiveShape(passiveThickness / 2., caloDim.dz(), planeLength / 2.); + // in the first calo layer we use a different material (LAr instead of Pb) for the inner passive material + // to sample more uniformly for the upstream correction. So we need to split the volume into + // passiveInnerShapeFirstLayer (for first layer) and passiveInnerShape (for other layers) + // passiveInner elements' lengths along electrode are length of layer0 and suf of lengths of other layers + // for the other passive elements, which are boxes, their length has to be corrected for the rotation + // needed in case of trapezoidal absorbers, leading to the 1 / cosPassiveAngle factor + // For the same reason, their thickness in the direction perpendicular to the electrode + // has to be scaled by 1 / cosPassiveAngle, and thus we use rotatedOuterThickness and rotatedGlueThickness + // here dd4hep::Trd1 passiveShape(passiveInnerThicknessMin / 2. + rotatedOuterThickness / 2. + rotatedGlueThickness / 2., passiveInnerThicknessMax / 2. + rotatedOuterThickness / 2. + rotatedGlueThickness / 2., caloDim.dz(), planeLength / 2.); - // inner layer is not in the first calo layer (to sample more uniformly in the layer where upstream correction is - // applied) - //dd4hep::Box passiveInnerShape(passiveInnerThickness / 2., caloDim.dz(), planeLength / 2. - layerHeight[0] / 2.); - dd4hep::Trd1 passiveInnerShape(passiveInnerThicknessLayer[1] / 2., passiveInnerThicknessMax / 2., caloDim.dz(), planeLength / 2. - layerHeight[0] / 2.); - //dd4hep::Box passiveInnerShapeFirstLayer(passiveInnerThickness / 2., caloDim.dz(), layerHeight[0] / 2.); dd4hep::Trd1 passiveInnerShapeFirstLayer(passiveInnerThicknessMin / 2., passiveInnerThicknessLayer[1] / 2., caloDim.dz(), layerHeight[0] / 2.); + dd4hep::Trd1 passiveInnerShape(passiveInnerThicknessLayer[1] / 2., passiveInnerThicknessMax / 2., caloDim.dz(), planeLength / 2. - layerHeight[0] / 2.); dd4hep::Box passiveOuterShape(passiveOuterThickness / 4., caloDim.dz(), planeLength / 2. / cosPassiveAngle); dd4hep::Box passiveGlueShape(passiveGlueThickness / 4., caloDim.dz(), planeLength / 2. / cosPassiveAngle); - // passive volume consists of inner part and two outer, joind by glue dd4hep::Volume passiveVol("passive", passiveShape, aLcdd.material("Air")); dd4hep::Volume passiveInnerVol(passiveInnerMaterial + "_passive", passiveInnerShape, aLcdd.material(passiveInnerMaterial)); @@ -310,7 +346,7 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, //dd4hep::Box layerPassiveInnerShape(passiveInnerThickness / 2., caloDim.dz(), layerHeight[iLayer] / 2.); dd4hep::Trd1 layerPassiveInnerShape(passiveInnerThicknessLayer[iLayer] / 2., passiveInnerThicknessLayer[iLayer+1] / 2., caloDim.dz(), layerHeight[iLayer] / 2.); dd4hep::Volume layerPassiveInnerVol(passiveInnerMaterial, layerPassiveInnerShape, - aLcdd.material(passiveInnerMaterial)); + aLcdd.material(passiveInnerMaterial)); layerPassiveInnerVol.setSensitiveDetector(aSensDet); dd4hep::PlacedVolume layerPassiveInnerPhysVol = passiveInnerVol.placeVolume(layerPassiveInnerVol, dd4hep::Position(0, 0, layerOffset)); @@ -359,6 +395,11 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, } } + // translate and rotate the elements of the module appropriately + // the Pb absorber does not need to be rotated, but the glue and + // the outer absorbers have to, in case of trapezoidal absorbers. + // The glue and steel absorbers also have to be translated in x-y + // to the proper positions on the two sides of the inner absorber dd4hep::PlacedVolume passiveInnerPhysVol = passiveVol.placeVolume(passiveInnerVol, dd4hep::Position(0, 0, layerHeight[0] / 2.)); dd4hep::PlacedVolume passiveInnerPhysVolFirstLayer = @@ -422,7 +463,12 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, ////////////////////////////// // ACTIVE ////////////////////////////// - // thickness of active layers at inner radius and outer ( = distance between passive plane and readout plane) + + // The active (LAr/LKr) elements are constructed subtracting from their + // envelope the readout and passive elements + // This requires some calculations to + + // Thickness of active layers at inner radius and outer ( = distance between passive plane and readout plane) // at inner radius: distance projected at plane perpendicular to readout plane double activeInThickness = Rmin * sin(dPhi / 2.) * cos(angle); activeInThickness -= passiveThickness * (0.5 - activePassiveOverlap); diff --git a/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v03_geo.cpp b/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v03_geo.cpp new file mode 100644 index 000000000..288b8c158 --- /dev/null +++ b/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v03_geo.cpp @@ -0,0 +1,697 @@ +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/Handle.h" +#include "XML/Utilities.h" + +#include + +// like v02, but in xml the layer dimensions are along the electrode +// directions, without rescaling by R/L where R = radial extent of ECAL +// and L = electrode length + +// todo: remove gaudi logging and properly capture output +#define endmsg std::endl +#define lLog std::cout +namespace MSG { +const std::string ERROR = "createECalBarrelInclined ERROR "; +const std::string DEBUG = "createECalBarrelInclined DEBUG "; +const std::string INFO = "createECalBarrelInclined INFO "; +} + +namespace det { +static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, + dd4hep::xml::Handle_t aXmlElement, + dd4hep::SensitiveDetector aSensDet) { + + dd4hep::xml::DetElement xmlDetElem = aXmlElement; + std::string nameDet = xmlDetElem.nameStr(); + dd4hep::xml::Dimension dim(xmlDetElem.dimensions()); + dd4hep::DetElement caloDetElem(nameDet, xmlDetElem.id()); + + // Create air envelope for the whole barrel + dd4hep::Volume envelopeVol(nameDet + "_vol", dd4hep::Tube(dim.rmin(), dim.rmax(), dim.dz()), + aLcdd.material("Air")); + envelopeVol.setVisAttributes(aLcdd, dim.visStr()); + + // Retrieve cryostat data + dd4hep::xml::DetElement cryostat = aXmlElement.child(_Unicode(cryostat)); + dd4hep::xml::Dimension cryoDim(cryostat.dimensions()); + double cryoThicknessFront = cryoDim.rmin2() - cryoDim.rmin1(); + dd4hep::xml::DetElement cryoFront = cryostat.child(_Unicode(front)); + dd4hep::xml::DetElement cryoBack = cryostat.child(_Unicode(back)); + dd4hep::xml::DetElement cryoSide = cryostat.child(_Unicode(side)); + bool cryoFrontSensitive = cryoFront.isSensitive(); + bool cryoBackSensitive = cryoBack.isSensitive(); + bool cryoSideSensitive = cryoSide.isSensitive(); + + // Retrieve active and passive material data + dd4hep::xml::DetElement calo = aXmlElement.child(_Unicode(calorimeter)); + dd4hep::xml::Dimension caloDim(calo.dimensions()); + dd4hep::xml::DetElement active = calo.child(_Unicode(active)); + std::string activeMaterial = active.materialStr(); + double activeThickness = active.thickness(); + + // Retrieve information about active/passive overlap + dd4hep::xml::DetElement overlap = active.child(_Unicode(overlap)); + double activePassiveOverlap = overlap.offset(); + if (activePassiveOverlap < 0 || activePassiveOverlap > 0.5) { + // todo: ServiceHandle incidentSvc("IncidentSvc", "ECalConstruction"); + lLog << MSG::ERROR << "Overlap between active and passive cannot be more than half of passive plane!" << endmsg; + //todo: incidentSvc->fireIncident(Incident("ECalConstruction", "GeometryFailure")); + } + + // Retrieve length of layers along electrode + dd4hep::xml::DetElement layers = calo.child(_Unicode(layers)); + uint numLayers = 0; + std::vector layerHeight; + double layersTotalHeight = 0; + for (dd4hep::xml::Collection_t layer_coll(layers, _Unicode(layer)); layer_coll; ++layer_coll) { + dd4hep::xml::Component layer = layer_coll; + numLayers += layer.repeat(); + for (int iLay = 0; iLay < layer.repeat(); iLay++) { + layerHeight.push_back(layer.thickness()); + } + layersTotalHeight += layer.repeat() * layer.thickness(); + } + lLog << MSG::DEBUG << "Total electrode length from calorimeter xml description (cm): " << layersTotalHeight/dd4hep::cm << endmsg; + + + // The following code checks if the xml geometry file contains a constant defining + // the number of layers the barrel. In that case, it makes the program abort + // if the number of planes in the xml is different from the one calculated from + // the geometry. This is because the number of layers is needed + // in other parts of the code (the readout for the FCC-ee ECAL with + // inclined modules). + int nLayers = -1; + try { + nLayers = aLcdd.constant("ECalBarrelNumLayers"); + } + catch(...) { + ; + } + if (nLayers > 0 && nLayers != int(numLayers)) { + lLog << MSG::ERROR << "Incorrect number of layers (ECalBarrelNumLayers) in readout in calorimeter xml description!" << endmsg; + lLog << MSG::ERROR << "Number of layers should be: " << numLayers << endmsg; + // todo: incidentSvc->fireIncident(Incident("ECalConstruction", "GeometryFailure")); + // make the code crash (incidentSvc does not work) + // Andre, Alvaro, assert replaced by exception + throw std::runtime_error("Incorrect number of layers (ECalBarrelNumLayers) in calorimeter xml description!"); + } + + // Retrieve information about the readout + dd4hep::xml::DetElement readout = calo.child(_Unicode(readout)); + std::string readoutMaterial = readout.materialStr(); + double readoutThickness = readout.thickness(); + + // Retrieve info about passive elements + // (glue, outer - typically steel, inner - typically Pb, and LAr in presampling layer) + dd4hep::xml::DetElement passive = calo.child(_Unicode(passive)); + dd4hep::xml::DetElement passiveInner = passive.child(_Unicode(inner)); + dd4hep::xml::DetElement passiveInnerMax = passive.child(_Unicode(innerMax)); + dd4hep::xml::DetElement passiveOuter = passive.child(_Unicode(outer)); + dd4hep::xml::DetElement passiveGlue = passive.child(_Unicode(glue)); + std::string passiveInnerMaterial = passiveInner.materialStr(); + std::string passiveOuterMaterial = passiveOuter.materialStr(); + std::string passiveGlueMaterial = passiveGlue.materialStr(); + double passiveInnerThicknessMin = passiveInner.thickness(); + double passiveInnerThicknessMax = passiveInnerMax.thickness(); + double passiveOuterThickness = passiveOuter.thickness(); + double passiveGlueThickness = passiveGlue.thickness(); + double passiveThickness = passiveInnerThicknessMin + passiveOuterThickness + passiveGlueThickness; + // inclination angle + double angle = passive.rotation().angle(); + // Retrieve info about bath + dd4hep::xml::DetElement bath = aXmlElement.child(_Unicode(bath)); + dd4hep::xml::Dimension bathDim(bath.dimensions()); + double bathRmin = bathDim.rmin(); + double bathRmax = bathDim.rmax(); + dd4hep::Tube bathOuterShape(bathRmin, bathRmax, caloDim.dz()); // make it 4 volumes + 5th for detector envelope + dd4hep::Tube bathAndServicesOuterShape(cryoDim.rmin2(), cryoDim.rmax1(), caloDim.dz()); // make it 4 volumes + 5th for detector envelope + + // 1. Create cryostat + if (cryoThicknessFront > 0) { + dd4hep::Tube cryoFrontShape(cryoDim.rmin1(), cryoDim.rmin2(), cryoDim.dz()); + dd4hep::Tube cryoBackShape(cryoDim.rmax1(), cryoDim.rmax2(), cryoDim.dz()); + dd4hep::Tube cryoSideOuterShape(cryoDim.rmin2(), cryoDim.rmax1(), cryoDim.dz()); + dd4hep::SubtractionSolid cryoSideShape(cryoSideOuterShape, bathAndServicesOuterShape); + lLog << MSG::INFO + << "ECAL cryostat: front: rmin (cm) = " << cryoDim.rmin1()/dd4hep::cm + << " rmax (cm) = " << cryoDim.rmin2()/dd4hep::cm + << " dz (cm) = " << cryoDim.dz()/dd4hep::cm << endmsg; + lLog << MSG::INFO + << "ECAL cryostat: back: rmin (cm) = " << cryoDim.rmax1()/dd4hep::cm + << " rmax (cm) = " << cryoDim.rmax2()/dd4hep::cm + << " dz (cm) = " << cryoDim.dz()/dd4hep::cm << endmsg; + lLog << MSG::INFO + << "ECAL cryostat: side: rmin (cm) = " << cryoDim.rmin2()/dd4hep::cm + << " rmax (cm) = " << cryoDim.rmax1()/dd4hep::cm + << " dz (cm) = " << (cryoDim.dz() - caloDim.dz())/dd4hep::cm << endmsg; + dd4hep::Volume cryoFrontVol(cryostat.nameStr()+"_front", cryoFrontShape, aLcdd.material(cryostat.materialStr())); + dd4hep::Volume cryoBackVol(cryostat.nameStr()+"_back", cryoBackShape, aLcdd.material(cryostat.materialStr())); + dd4hep::Volume cryoSideVol(cryostat.nameStr()+"_side", cryoSideShape, aLcdd.material(cryostat.materialStr())); + dd4hep::PlacedVolume cryoFrontPhysVol = envelopeVol.placeVolume(cryoFrontVol); + dd4hep::PlacedVolume cryoBackPhysVol = envelopeVol.placeVolume(cryoBackVol); + dd4hep::PlacedVolume cryoSidePhysVol = envelopeVol.placeVolume(cryoSideVol); + if (cryoFrontSensitive) { + cryoFrontVol.setSensitiveDetector(aSensDet); + cryoFrontPhysVol.addPhysVolID("cryo", 1); + cryoFrontPhysVol.addPhysVolID("type", 1); + lLog << MSG::INFO << "ECAL Cryostat front volume set as sensitive" << endmsg; + } + if (cryoBackSensitive) { + cryoBackVol.setSensitiveDetector(aSensDet); + cryoBackPhysVol.addPhysVolID("cryo", 1); + cryoBackPhysVol.addPhysVolID("type", 2); + lLog << MSG::INFO << "ECAL Cryostat back volume set as sensitive" << endmsg; + } + if (cryoSideSensitive) { + cryoSideVol.setSensitiveDetector(aSensDet); + cryoSidePhysVol.addPhysVolID("cryo", 1); + cryoSidePhysVol.addPhysVolID("type", 3); + lLog << MSG::INFO << "ECAL Cryostat front volume set as sensitive" << endmsg; + } + dd4hep::DetElement cryoFrontDetElem(caloDetElem, "cryo_front", 0); + cryoFrontDetElem.setPlacement(cryoFrontPhysVol); + dd4hep::DetElement cryoBackDetElem(caloDetElem, "cryo_back", 0); + cryoBackDetElem.setPlacement(cryoBackPhysVol); + dd4hep::DetElement cryoSideDetElem(caloDetElem, "cryo_side", 0); + cryoSideDetElem.setPlacement(cryoSidePhysVol); + // 1.2. Create place-holder for services + dd4hep::Tube servicesFrontShape(cryoDim.rmin2(), bathRmin, caloDim.dz()); + dd4hep::Tube servicesBackShape(bathRmax, cryoDim.rmax1(), caloDim.dz()); + lLog << MSG::INFO + << "ECAL services: front: rmin (cm) = " << cryoDim.rmin2()/dd4hep::cm + << " rmax (cm) = " << bathRmin/dd4hep::cm/dd4hep::cm + << " dz (cm) = " << caloDim.dz()/dd4hep::cm << endmsg; + lLog << MSG::INFO + << "ECAL services: back: rmin (cm) = " << bathRmax/dd4hep::cm + << " rmax (cm) = " << cryoDim.rmax1()/dd4hep::cm + << " dz (cm) = " << caloDim.dz()/dd4hep::cm << endmsg; + dd4hep::Volume servicesFrontVol("services_front", servicesFrontShape, aLcdd.material(activeMaterial)); + dd4hep::Volume servicesBackVol("services_back", servicesBackShape, aLcdd.material(activeMaterial)); + dd4hep::PlacedVolume servicesFrontPhysVol = envelopeVol.placeVolume(servicesFrontVol); + dd4hep::PlacedVolume servicesBackPhysVol = envelopeVol.placeVolume(servicesBackVol); + if (cryoFrontSensitive) { + servicesFrontVol.setSensitiveDetector(aSensDet); + servicesFrontPhysVol.addPhysVolID("cryo", 1); + servicesFrontPhysVol.addPhysVolID("type", 4); + lLog << MSG::INFO << "ECAL Services front volume set as sensitive" << endmsg; + } + if (cryoBackSensitive) { + servicesBackVol.setSensitiveDetector(aSensDet); + servicesBackPhysVol.addPhysVolID("cryo", 1); + servicesBackPhysVol.addPhysVolID("type", 5); + lLog << MSG::INFO << "ECAL Services back volume set as sensitive" << endmsg; + } + dd4hep::DetElement servicesFrontDetElem(caloDetElem, "services_front", 0); + servicesFrontDetElem.setPlacement(servicesFrontPhysVol); + dd4hep::DetElement servicesBackDetElem(caloDetElem, "services_back", 0); + servicesBackDetElem.setPlacement(servicesBackPhysVol); + } + + // 2. Create bath that is inside the cryostat and surrounds the detector + // Bath is filled with active material -> but not sensitive + dd4hep::Volume bathVol(activeMaterial + "_bath", bathOuterShape, aLcdd.material(activeMaterial)); + lLog << MSG::INFO << "ECAL bath: material = " << activeMaterial + << " rmin (cm) = " << bathRmin/dd4hep::cm + << " rmax (cm) = " << bathRmax/dd4hep::cm << endmsg; + double Rmin = caloDim.rmin(); + double Rmax = caloDim.rmax(); + double dR = Rmax - Rmin; + lLog << MSG::INFO + << "ECAL calorimeter volume rmin (cm) = " << Rmin/dd4hep::cm + << " rmax (cm) = " << Rmax/dd4hep::cm << endmsg; + lLog << MSG::INFO << "ECAL thickness of calorimeter (cm) = " << dR/dd4hep::cm << endmsg; + lLog << MSG::INFO << "ECAL thickness in front of calorimeter (between cryostat front and calorimeter) (cm) = " << (Rmin - cryoDim.rmin2())/dd4hep::cm << endmsg; + lLog << MSG::INFO << "ECAL thickness behind calorimeter (between calorimeter and cryostat back) (cm) = " << (cryoDim.rmax1() - Rmax)/dd4hep::cm << endmsg; + + // 3. Create the calorimeter by placing the passive material, trapezoid active layers, readout and again trapezoid + // active layers in the bath. + // sensitive detector for the layers + dd4hep::SensitiveDetector sd = aSensDet; + dd4hep::xml::Dimension sdType = xmlDetElem.child(_U(sensitive)); + sd.setType(sdType.typeStr()); + + // 3.a. Create the passive planes, readout in between of 2 passive planes and the remaining space fill with active + // material + + ////////////////////////////// + // PASSIVE PLANES + ////////////////////////////// + + // passive volumes consist of inner part and two outer, joined by glue + lLog << MSG::INFO << "Passive elements:" << endmsg; + lLog << MSG::INFO << " material in inner part of absorber (except 1st layer) = " << passiveInnerMaterial << endmsg; + lLog << MSG::INFO << " material in inner part of absorber (1st layer) = " << activeMaterial << endmsg; + lLog << MSG::INFO << " material in outer part of absorber = " << passiveOuterMaterial << endmsg; + lLog << MSG::INFO << " material in between = " << passiveGlueMaterial << endmsg; + lLog << MSG::INFO << " thickness of inner part at inner radius (cm) = " << passiveInnerThicknessMin/dd4hep::cm << endmsg; + lLog << MSG::INFO << " thickness of inner part at outer radius (cm) = " << passiveInnerThicknessMax/dd4hep::cm << endmsg; + lLog << MSG::INFO << " thickness of outer part (cm) = " << passiveOuterThickness/dd4hep::cm << endmsg; + lLog << MSG::INFO << " thickness of middle part (cm) = " << passiveGlueThickness/dd4hep::cm << endmsg; + lLog << MSG::INFO << " total thickness of absorber (cm) = " << passiveThickness/dd4hep::cm << endmsg; + + lLog << MSG::INFO << "Electrodes:" << endmsg; + lLog << MSG::INFO << " rotation angle (radians) = " << angle << " , (degrees) = " << angle*57.295780 << endmsg; + + // calculate number of modules + uint numPlanes = + round(M_PI / asin((passiveThickness + activeThickness + readoutThickness) / (2. * Rmin * cos(angle)))); + + double dPhi = 2. * M_PI / numPlanes; + lLog << MSG::INFO << " number of planes (calculated) = " << numPlanes << " , azim. angle difference = " << dPhi << endmsg; + lLog << MSG::INFO << " distance at inner radius (cm) = " << 2. * M_PI * Rmin/dd4hep::cm / numPlanes << endmsg; + lLog << MSG::INFO << " distance at outer radius (cm) = " << 2. * M_PI * Rmax/dd4hep::cm / numPlanes << endmsg; + + // The following code checks if the xml geometry file contains a constant defining + // the number of planes in the barrel. In that case, it makes the program abort + // if the number of planes in the xml is different from the one calculated from + // the geometry. This is because the number of plane information (retrieved from the + // xml) is used in other parts of the code (the readout for the FCC-ee ECAL with + // inclined modules). In principle the code above should be refactored so that the number + // of planes is one of the inputs of the calculation and other geometrical parameters + // are adjusted accordingly. This is left for the future, and we use the workaround + // below to enforce for the time being that the number of planes is "correct" + int nModules = -1; + try { + nModules = aLcdd.constant("ECalBarrelNumPlanes"); + } + catch(...) { + ; + } + if (nModules > 0 && nModules != int(numPlanes)) { + lLog << MSG::ERROR << "Incorrect number of planes (ECalBarrelNumPlanes) in calorimeter xml description!" << endmsg; + // todo: incidentSvc->fireIncident(Incident("ECalConstruction", "GeometryFailure")); + // make the code crash (incidentSvc does not work) + // Andre, Alvaro, assert replaced by exception + throw std::runtime_error("Incorrect number of planes (ECalBarrelNumPlanes) in calorimeter xml description!"); + } + // Readout is in the middle between two passive planes + double offsetPassivePhi = caloDim.offset() + dPhi / 2.; + double offsetReadoutPhi = caloDim.offset() + 0; + lLog << MSG::INFO << " readout material = " << readoutMaterial << endmsg; + lLog << MSG::INFO << " thickness of readout planes (cm) = " << readoutThickness/dd4hep::cm << endmsg; + lLog << MSG::INFO << " number of layers = " << numLayers << endmsg; + + + // electrode length, given inclination angle and min/max radius of the active calorimeter volume + double planeLength = -Rmin * cos(angle) + sqrt(pow(Rmax, 2) - pow(Rmin * sin(angle), 2)); + + double runningHeight = 0.; + lLog << MSG::INFO << " total length from Rmin, Rmax and angle (cm) = " << planeLength/dd4hep::cm << endmsg; + lLog << MSG::INFO << " predicted layer radii: " << endmsg; + for (uint iLay = 0; iLay < numLayers; iLay++) { + double Lmin = runningHeight; + double Lmax = runningHeight + layerHeight[iLay]; + runningHeight += layerHeight[iLay]; + double rMin = sqrt(Rmin*Rmin + Lmin*Lmin + 2*Rmin*Lmin*cos(angle)); + double rMax = sqrt(Rmin*Rmin + Lmax*Lmax + 2*Rmin*Lmax*cos(angle)); + lLog << MSG::INFO << " layer " << iLay << " (cm) = " << rMin/dd4hep::cm << " - " << rMax/dd4hep::cm << endmsg; + } + + // check that electrode length is consistent with calorimeter radial extent + // and inclination angle to within 0.5 mm + if (fabs(planeLength - layersTotalHeight) > 0.05*dd4hep::cm) { + lLog << MSG::ERROR << " the sum of the electrode lengths per layer in the calorimeter xml file is not consistent with the length calculated from the calorimeter radial extent and the inclination angle" << endmsg; + throw std::runtime_error("Incorrect length of electrode layers in calorimeter xml description!"); + } + // calculate the thickness of the passive material in each layer + // it's not constant in case of trapezoidal absorbers (passiveInnerThicknessMax != passiveInnerThicknessMin) + // the code calculates the (max) passive thickness per layer i.e. at Rout of layer + // rescaling by runningHeight / Ltot + std::vector passiveInnerThicknessLayer(numLayers+1); + lLog << MSG::DEBUG << "passiveInnerThickness: " << endmsg; + runningHeight = 0.; + for (uint iLay = 0; iLay < numLayers; iLay++) { + passiveInnerThicknessLayer[iLay] = passiveInnerThicknessMin + (passiveInnerThicknessMax - passiveInnerThicknessMin) * + (runningHeight) / layersTotalHeight; + lLog << MSG::DEBUG << " layer " << iLay << " = " << passiveInnerThicknessLayer[iLay] << " cm" << endmsg; + } + passiveInnerThicknessLayer[numLayers] = passiveInnerThicknessMin + (passiveInnerThicknessMax - passiveInnerThicknessMin) * + (runningHeight) / layersTotalHeight; + + lLog << MSG::DEBUG << " layer " << numLayers << " = " << passiveInnerThicknessLayer[numLayers] << " cm" << endmsg; + + // calculate the angle of the passive elements if trapezoidal absorbers are used (Max != Min) + // if parallel absorbers are used then passiveAngle = 0 and cosPassiveAngle = 1 + double passiveAngle = atan2((passiveInnerThicknessMax - passiveInnerThicknessMin) / 2., planeLength); + double cosPassiveAngle = cos(passiveAngle); + double rotatedOuterThickness = passiveOuterThickness / cosPassiveAngle; + double rotatedGlueThickness = passiveGlueThickness / cosPassiveAngle; + + // distance from the center of the electrode to the center of the 1st layer, in the electrode direction + double layerFirstOffset = -planeLength / 2. + layerHeight[0] / 2.; + + // in the first calo layer we use a different material (LAr instead of Pb) for the inner passive material + // to sample more uniformly for the upstream correction. So we need to split the volume into + // passiveInnerShapeFirstLayer (for first layer) and passiveInnerShape (for other layers) + // passiveInner elements' lengths along electrode are length of layer0 and suf of lengths of other layers + // for the other passive elements, which are boxes, their length has to be corrected for the rotation + // needed in case of trapezoidal absorbers, leading to the 1 / cosPassiveAngle factor + // For the same reason, their thickness in the direction perpendicular to the electrode + // has to be scaled by 1 / cosPassiveAngle, and thus we use rotatedOuterThickness and rotatedGlueThickness + // here + dd4hep::Trd1 passiveShape(passiveInnerThicknessMin / 2. + rotatedOuterThickness / 2. + rotatedGlueThickness / 2., + passiveInnerThicknessMax / 2. + rotatedOuterThickness / 2. + rotatedGlueThickness / 2., + caloDim.dz(), planeLength / 2.); + dd4hep::Trd1 passiveInnerShapeFirstLayer(passiveInnerThicknessMin / 2., passiveInnerThicknessLayer[1] / 2., caloDim.dz(), layerHeight[0] / 2.); + dd4hep::Trd1 passiveInnerShape(passiveInnerThicknessLayer[1] / 2., passiveInnerThicknessMax / 2., caloDim.dz(), planeLength / 2. - layerHeight[0] / 2.); + dd4hep::Box passiveOuterShape(passiveOuterThickness / 4., caloDim.dz(), planeLength / 2. / cosPassiveAngle); + dd4hep::Box passiveGlueShape(passiveGlueThickness / 4., caloDim.dz(), planeLength / 2. / cosPassiveAngle); + dd4hep::Volume passiveVol("passive", passiveShape, aLcdd.material("Air")); + dd4hep::Volume passiveInnerVol(passiveInnerMaterial + "_passive", passiveInnerShape, + aLcdd.material(passiveInnerMaterial)); + dd4hep::Volume passiveInnerVolFirstLayer(activeMaterial + "_passive", passiveInnerShapeFirstLayer, + aLcdd.material(activeMaterial)); + dd4hep::Volume passiveOuterVol(passiveOuterMaterial + "_passive", passiveOuterShape, + aLcdd.material(passiveOuterMaterial)); + dd4hep::Volume passiveGlueVol(passiveGlueMaterial + "_passive", passiveGlueShape, + aLcdd.material(passiveGlueMaterial)); + + if (passiveInner.isSensitive()) { + lLog << MSG::DEBUG << "Passive inner volume set as sensitive" << endmsg; + // inner part starts at second layer + double layerOffset = layerFirstOffset + layerHeight[1] / 2.; + for (uint iLayer = 1; iLayer < numLayers; iLayer++) { + //dd4hep::Box layerPassiveInnerShape(passiveInnerThickness / 2., caloDim.dz(), layerHeight[iLayer] / 2.); + dd4hep::Trd1 layerPassiveInnerShape(passiveInnerThicknessLayer[iLayer] / 2., passiveInnerThicknessLayer[iLayer+1] / 2., caloDim.dz(), layerHeight[iLayer] / 2.); + dd4hep::Volume layerPassiveInnerVol(passiveInnerMaterial, layerPassiveInnerShape, + aLcdd.material(passiveInnerMaterial)); + layerPassiveInnerVol.setSensitiveDetector(aSensDet); + dd4hep::PlacedVolume layerPassiveInnerPhysVol = + passiveInnerVol.placeVolume(layerPassiveInnerVol, dd4hep::Position(0, 0, layerOffset)); + layerPassiveInnerPhysVol.addPhysVolID("layer", iLayer); + dd4hep::DetElement layerPassiveInnerDetElem("layer", iLayer); + layerPassiveInnerDetElem.setPlacement(layerPassiveInnerPhysVol); + if (iLayer != numLayers - 1) { + layerOffset += layerHeight[iLayer] / 2. + layerHeight[iLayer + 1] / 2.; + } + } + } + if (passiveOuter.isSensitive()) { + lLog << MSG::DEBUG << "Passive outer volume set as sensitive" << endmsg; + double layerOffset = layerFirstOffset / cosPassiveAngle; + for (uint iLayer = 0; iLayer < numLayers; iLayer++) { + dd4hep::Box layerPassiveOuterShape(passiveOuterThickness / 4., caloDim.dz(), layerHeight[iLayer] / 2. / cosPassiveAngle); + dd4hep::Volume layerPassiveOuterVol(passiveOuterMaterial, layerPassiveOuterShape, + aLcdd.material(passiveOuterMaterial)); + layerPassiveOuterVol.setSensitiveDetector(aSensDet); + dd4hep::PlacedVolume layerPassiveOuterPhysVol = + passiveOuterVol.placeVolume(layerPassiveOuterVol, dd4hep::Position(0, 0, layerOffset)); + layerPassiveOuterPhysVol.addPhysVolID("layer", iLayer); + dd4hep::DetElement layerPassiveOuterDetElem("layer", iLayer); + layerPassiveOuterDetElem.setPlacement(layerPassiveOuterPhysVol); + if (iLayer != numLayers - 1) { + layerOffset += (layerHeight[iLayer] / 2. + layerHeight[iLayer + 1] / 2.) / cosPassiveAngle; + } + } + } + if (passiveGlue.isSensitive()) { + lLog << MSG::DEBUG << "Passive glue volume set as sensitive" << endmsg; + double layerOffset = layerFirstOffset / cosPassiveAngle; + for (uint iLayer = 0; iLayer < numLayers; iLayer++) { + dd4hep::Box layerPassiveGlueShape(passiveGlueThickness / 4., caloDim.dz(), layerHeight[iLayer] / 2. / cosPassiveAngle); + dd4hep::Volume layerPassiveGlueVol(passiveGlueMaterial, layerPassiveGlueShape, + aLcdd.material(passiveGlueMaterial)); + layerPassiveGlueVol.setSensitiveDetector(aSensDet); + dd4hep::PlacedVolume layerPassiveGluePhysVol = + passiveGlueVol.placeVolume(layerPassiveGlueVol, dd4hep::Position(0, 0, layerOffset)); + layerPassiveGluePhysVol.addPhysVolID("layer", iLayer); + dd4hep::DetElement layerPassiveGlueDetElem("layer", iLayer); + layerPassiveGlueDetElem.setPlacement(layerPassiveGluePhysVol); + if (iLayer != numLayers - 1) { + layerOffset += (layerHeight[iLayer] / 2. + layerHeight[iLayer + 1] / 2.) / cosPassiveAngle; + } + } + } + + // translate and rotate the elements of the module appropriately + // the Pb absorber does not need to be rotated, but the glue and + // the outer absorbers have to, in case of trapezoidal absorbers. + // The glue and steel absorbers also have to be translated in x-y + // to the proper positions on the two sides of the inner absorber + dd4hep::PlacedVolume passiveInnerPhysVol = + passiveVol.placeVolume(passiveInnerVol, dd4hep::Position(0, 0, layerHeight[0] / 2.)); + dd4hep::PlacedVolume passiveInnerPhysVolFirstLayer = + passiveVol.placeVolume(passiveInnerVolFirstLayer, dd4hep::Position(0, 0, layerFirstOffset)); + dd4hep::PlacedVolume passiveOuterPhysVolBelow = passiveVol.placeVolume( + passiveOuterVol, + dd4hep::Transform3D(dd4hep::RotationY(-passiveAngle), + dd4hep::Position(-(passiveInnerThicknessMin + passiveInnerThicknessMax) / 4. - + rotatedGlueThickness / 2. - rotatedOuterThickness / 4., 0, 0))); + dd4hep::PlacedVolume passiveOuterPhysVolAbove = passiveVol.placeVolume( + passiveOuterVol, + dd4hep::Transform3D(dd4hep::RotationY(passiveAngle), + dd4hep::Position((passiveInnerThicknessMin + passiveInnerThicknessMax) / 4. + + rotatedGlueThickness / 2. + rotatedOuterThickness / 4., 0, 0))); + dd4hep::PlacedVolume passiveGluePhysVolBelow = passiveVol.placeVolume( + passiveGlueVol, + dd4hep::Transform3D(dd4hep::RotationY(-passiveAngle), + dd4hep::Position(-(passiveInnerThicknessMin + passiveInnerThicknessMax) / 4. - + rotatedGlueThickness / 4., 0, 0))); + dd4hep::PlacedVolume passiveGluePhysVolAbove = passiveVol.placeVolume( + passiveGlueVol, + dd4hep::Transform3D(dd4hep::RotationY(passiveAngle), + dd4hep::Position((passiveInnerThicknessMin + passiveInnerThicknessMax) / 4. + + rotatedGlueThickness / 4., 0, 0))); + passiveInnerPhysVol.addPhysVolID("subtype", 0); + passiveInnerPhysVolFirstLayer.addPhysVolID("subtype", 0); + passiveOuterPhysVolBelow.addPhysVolID("subtype", 1); + passiveOuterPhysVolAbove.addPhysVolID("subtype", 2); + passiveGluePhysVolBelow.addPhysVolID("subtype", 3); + passiveGluePhysVolAbove.addPhysVolID("subtype", 4); + if (passiveInner.isSensitive()) { + passiveInnerVolFirstLayer.setSensitiveDetector(aSensDet); + passiveInnerPhysVolFirstLayer.addPhysVolID("layer", 0); + dd4hep::DetElement passiveInnerDetElemFirstLayer("layer", 0); + passiveInnerDetElemFirstLayer.setPlacement(passiveInnerPhysVolFirstLayer); + } + + ////////////////////////////// + // READOUT PLANES + ////////////////////////////// + dd4hep::Box readoutShape(readoutThickness / 2., caloDim.dz(), planeLength / 2.); + dd4hep::Volume readoutVol(readoutMaterial, readoutShape, aLcdd.material(readoutMaterial)); + if (readout.isSensitive()) { + lLog << MSG::INFO << "ECAL readout volume set as sensitive" << endmsg; + double layerOffset = layerFirstOffset; + for (uint iLayer = 0; iLayer < numLayers; iLayer++) { + dd4hep::Box layerReadoutShape(readoutThickness / 2., caloDim.dz(), layerHeight[iLayer] / 2.); + dd4hep::Volume layerReadoutVol(readoutMaterial, layerReadoutShape, aLcdd.material(readoutMaterial)); + layerReadoutVol.setSensitiveDetector(aSensDet); + dd4hep::PlacedVolume layerReadoutPhysVol = + readoutVol.placeVolume(layerReadoutVol, dd4hep::Position(0, 0, layerOffset)); + layerReadoutPhysVol.addPhysVolID("layer", iLayer); + dd4hep::DetElement layerReadoutDetElem("layer", iLayer); + layerReadoutDetElem.setPlacement(layerReadoutPhysVol); + if (iLayer != numLayers - 1) { + layerOffset += layerHeight[iLayer] / 2. + layerHeight[iLayer + 1] / 2.; + } + } + } + + ////////////////////////////// + // ACTIVE + ////////////////////////////// + + // The active (LAr/LKr) elements are constructed subtracting from their + // envelope the readout and passive elements + // This requires some calculations to + + // Thickness of active layers at inner radius and outer ( = distance between passive plane and readout plane) + // at inner radius: distance projected at plane perpendicular to readout plane + double activeInThickness = Rmin * sin(dPhi / 2.) * cos(angle); + activeInThickness -= passiveThickness * (0.5 - activePassiveOverlap); + // at outer radius: distance projected at plane perpendicular to readout plane + double activeOutThickness = (Rmin + planeLength) * sin(dPhi / 2.) * cos(angle); + // make correction for outer readius caused by inclination angle + // first calculate intersection of readout plane and plane parallel to shifted passive plane + double xIntersect = (Rmin * (tan(angle) - cos(dPhi / 2.) * tan(angle + dPhi / 2.)) - planeLength * sin(dPhi / 2.)) / + (tan(angle) - tan(angle + dPhi / 2.)); + double yIntersect = tan(angle) * xIntersect + Rmin * (sin(dPhi / 2.) - tan(angle)) + planeLength * sin(dPhi / 2.); + // distance from inner radius to intersection + double correction = + planeLength - sqrt(pow(xIntersect - Rmin * cos(dPhi / 2), 2) + pow(yIntersect - Rmin * sin(dPhi / 2), 2)); + // correction to the active thickness + activeOutThickness += 2. * correction * sin(dPhi / 4.); + activeOutThickness -= passiveThickness * (0.5 - activePassiveOverlap); + // print the active layer dimensions + double activeInThicknessAfterSubtraction = + 2. * activeInThickness - readoutThickness - 2. * activePassiveOverlap * passiveThickness; + double activeOutThicknessAfterSubtraction = + 2. * activeOutThickness - readoutThickness - 2. * activePassiveOverlap * + (passiveThickness + passiveInnerThicknessMax - passiveInnerThicknessMin); // correct thickness for trapezoid + lLog << MSG::INFO << "Active elements:" << endmsg; + lLog << MSG::INFO << " material = " << activeMaterial << endmsg; + lLog << MSG::INFO << " thickness at inner radius (cm) = " << activeInThicknessAfterSubtraction/dd4hep::cm << endmsg; + lLog << MSG::INFO << " thickness at outer radius (cm) = " << activeOutThicknessAfterSubtraction/dd4hep::cm << endmsg; + lLog << MSG::INFO << " thickness relative increase from inner to outer radius = " + << (activeOutThicknessAfterSubtraction - activeInThicknessAfterSubtraction) * 100 / + activeInThicknessAfterSubtraction + << " %." << endmsg; + lLog << MSG::INFO + << " active passive initial overlap (before subtraction) (cm) = " << passiveThickness/dd4hep::cm * activePassiveOverlap + << " = " << activePassiveOverlap * 100 << " %" << endmsg; + + // creating shape for rows of layers (active material between two passive planes, with readout in the middle) + // first define area between two passive planes, area can reach up to the symmetry axis of passive plane + dd4hep::Trd1 activeOuterShape(activeInThickness, activeOutThickness, caloDim.dz(), planeLength / 2.); + // subtract readout shape from the middle + dd4hep::SubtractionSolid activeShapeNoReadout(activeOuterShape, readoutShape); + + // make calculation for active plane that is inclined with 0 deg (= offset + angle) + double Cx = Rmin * cos(-angle) + planeLength / 2.; + double Cy = Rmin * sin(-angle); + double Ax = Rmin * cos(-angle + dPhi / 2.) + planeLength / 2. * cos(dPhi / 2.); + double Ay = Rmin * sin(-angle + dPhi / 2.) + planeLength / 2. * sin(dPhi / 2.); + double CAx = fabs(Ax - Cx); + double CAy = fabs(Ay - Cy); + double zprim, xprim; + zprim = CAx; + xprim = CAy; + + double Bx = Rmin * cos(-angle - dPhi / 2.) + planeLength / 2. * cos(-dPhi / 2.); + double By = Rmin * sin(-angle - dPhi / 2.) + planeLength / 2. * sin(-dPhi / 2.); + double CBx = fabs(Bx - Cx); + double CBy = fabs(By - Cy); + double zprimB, xprimB; + zprimB = CBx; + xprimB = CBy; + + // subtract passive volume above + dd4hep::SubtractionSolid activeShapeNoPassiveAbove( + activeShapeNoReadout, passiveShape, + dd4hep::Transform3D(dd4hep::RotationY(-dPhi / 2.), + dd4hep::Position(-fabs(xprim), 0, fabs(zprim)))); + // subtract passive volume below + dd4hep::SubtractionSolid activeShape( + activeShapeNoPassiveAbove, passiveShape, + dd4hep::Transform3D(dd4hep::RotationY(dPhi / 2.), + dd4hep::Position(fabs(xprimB), 0, -fabs(zprimB)))); + dd4hep::Volume activeVol("active", activeShape, aLcdd.material("Air")); + + std::vector layerPhysVols; + // place layers within active volume + std::vector layerInThickness; + std::vector layerOutThickness; + double layerIncreasePerUnitThickness = (activeOutThickness - activeInThickness) / layersTotalHeight; + for (uint iLay = 0; iLay < numLayers; iLay++) { + if (iLay == 0) { + layerInThickness.push_back(activeInThickness); + } else { + layerInThickness.push_back(layerOutThickness[iLay - 1]); + } + layerOutThickness.push_back(layerInThickness[iLay] + layerIncreasePerUnitThickness * layerHeight[iLay]); + } + double layerOffset = layerFirstOffset; + for (uint iLayer = 0; iLayer < numLayers; iLayer++) { + dd4hep::Trd1 layerOuterShape(layerInThickness[iLayer], layerOutThickness[iLayer], caloDim.dz(), layerHeight[iLayer] / 2.); + dd4hep::SubtractionSolid layerShapeNoReadout(layerOuterShape, readoutShape); + dd4hep::SubtractionSolid layerShapeNoPassiveAbove( + layerShapeNoReadout, passiveShape, + dd4hep::Transform3D(dd4hep::RotationY(-dPhi / 2.), + dd4hep::Position(-fabs(xprim), 0, fabs(zprim) - layerOffset))); + // subtract passive volume below + dd4hep::SubtractionSolid layerShape( + layerShapeNoPassiveAbove, passiveShape, + dd4hep::Transform3D(dd4hep::RotationY(dPhi / 2.), + dd4hep::Position(fabs(xprimB), 0, -fabs(zprimB) - layerOffset))); + dd4hep::Volume layerVol("layer", layerShape, aLcdd.material(activeMaterial)); + layerVol.setSensitiveDetector(aSensDet); + layerPhysVols.push_back(activeVol.placeVolume(layerVol, dd4hep::Position(0, 0, layerOffset))); + layerPhysVols.back().addPhysVolID("layer", iLayer); + if (iLayer != numLayers - 1) { + layerOffset += layerHeight[iLayer] / 2. + layerHeight[iLayer + 1] / 2.; + } + } + + dd4hep::DetElement bathDetElem(caloDetElem, "bath", 1); + std::vector activePhysVols; + // Next place elements: passive planes, readout planes and rows of layers + for (uint iPlane = 0; iPlane < numPlanes; iPlane++) { + // first calculate positions of passive and readout planes + // PASSIVE + // calculate centre position of the plane without plane rotation + double phi = offsetPassivePhi + iPlane * dPhi; + double xRadial = (Rmin + planeLength / 2.) * cos(phi); + double yRadial = (Rmin + planeLength / 2.) * sin(phi); + // calculate position of the beginning of plane + double xRmin = Rmin * cos(phi); + double yRmin = Rmin * sin(phi); + // rotate centre by angle wrt beginning of plane + double xRotated = xRmin + (xRadial - xRmin) * cos(angle) - (yRadial - yRmin) * sin(angle); + double yRotated = yRmin + (xRadial - xRmin) * sin(angle) + (yRadial - yRmin) * cos(angle); + dd4hep::Transform3D transform(dd4hep::RotationX(-M_PI / 2.) // to get in XY plane + * + dd4hep::RotationY(M_PI / 2. // to get pointed towards centre + - + phi - angle), + dd4hep::Position(xRotated, yRotated, 0)); + dd4hep::PlacedVolume passivePhysVol = bathVol.placeVolume(passiveVol, transform); + passivePhysVol.addPhysVolID("module", iPlane); + passivePhysVol.addPhysVolID("type", 1); // 0 = active, 1 = passive, 2 = readout + dd4hep::DetElement passiveDetElem(bathDetElem, "passive" + std::to_string(iPlane), iPlane); + passiveDetElem.setPlacement(passivePhysVol); + + // READOUT + // calculate centre position of the plane without plane rotation + double phiRead = offsetReadoutPhi + iPlane * dPhi; + double xRadialRead = (Rmin + planeLength / 2.) * cos(phiRead); + double yRadialRead = (Rmin + planeLength / 2.) * sin(phiRead); + // calculate position of the beginning of plane + double xRminRead = Rmin * cos(phiRead); + double yRminRead = Rmin * sin(phiRead); + // rotate centre by angle wrt beginning of plane + double xRotatedRead = xRminRead + (xRadialRead - xRminRead) * cos(angle) - (yRadialRead - yRminRead) * sin(angle); + double yRotatedRead = yRminRead + (xRadialRead - xRminRead) * sin(angle) + (yRadialRead - yRminRead) * cos(angle); + dd4hep::Transform3D transformRead( + dd4hep::RotationX(-M_PI / 2.) // to get in XY plane + * + dd4hep::RotationY(M_PI / 2. // to get pointed towards centre + - + phiRead - angle), + dd4hep::Position(xRotatedRead, yRotatedRead, 0)); + dd4hep::PlacedVolume readoutPhysVol = bathVol.placeVolume(readoutVol, transformRead); + readoutPhysVol.addPhysVolID("module", iPlane); + readoutPhysVol.addPhysVolID("type", 2); // 0 = active, 1 = passive, 2 = readout + dd4hep::DetElement readoutDetElem(bathDetElem, "readout" + std::to_string(iPlane), iPlane); + readoutDetElem.setPlacement(readoutPhysVol); + + // ACTIVE + dd4hep::Rotation3D rotationActive(dd4hep::RotationX(-M_PI / 2) * + dd4hep::RotationY(M_PI / 2 - phiRead - angle)); + activePhysVols.push_back(bathVol.placeVolume( + activeVol, + dd4hep::Transform3D(rotationActive, dd4hep::Position(xRotatedRead, yRotatedRead, 0)))); + activePhysVols.back().addPhysVolID("module", iPlane); + activePhysVols.back().addPhysVolID("type", 0); // 0 = active, 1 = passive, 2 = readout + } + dd4hep::PlacedVolume bathPhysVol = envelopeVol.placeVolume(bathVol); + bathDetElem.setPlacement(bathPhysVol); + for (uint iPlane = 0; iPlane < numPlanes; iPlane++) { + dd4hep::DetElement activeDetElem(bathDetElem, "active" + std::to_string(iPlane), iPlane); + activeDetElem.setPlacement(activePhysVols[iPlane]); + for (uint iLayer = 0; iLayer < numLayers; iLayer++) { + dd4hep::DetElement layerDetElem(activeDetElem, "layer" + std::to_string(iLayer), iLayer); + layerDetElem.setPlacement(layerPhysVols[iLayer]); + } + } + + // Place the envelope + dd4hep::Volume motherVol = aLcdd.pickMotherVolume(caloDetElem); + dd4hep::PlacedVolume envelopePhysVol = motherVol.placeVolume(envelopeVol); + envelopePhysVol.addPhysVolID("system", xmlDetElem.id()); + caloDetElem.setPlacement(envelopePhysVol); + + // Create caloData object + auto caloData = new dd4hep::rec::LayeredCalorimeterData; + caloData->layoutType = dd4hep::rec::LayeredCalorimeterData::BarrelLayout; + caloDetElem.addExtension(caloData); + + // Set type flags + dd4hep::xml::setDetectorTypeFlag(xmlDetElem, caloDetElem); + + return caloDetElem; +} +} // namespace det + +DECLARE_DETELEMENT(ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v03, det::createECalBarrelInclined) diff --git a/lcgeoTests/CMakeLists.txt b/lcgeoTests/CMakeLists.txt index bf13a7940..59dac77fa 100644 --- a/lcgeoTests/CMakeLists.txt +++ b/lcgeoTests/CMakeLists.txt @@ -93,6 +93,13 @@ ADD_TEST( t_${test_name} "${CMAKE_INSTALL_PREFIX}/bin/run_test_${PackageName}.sh ddsim --compactFile=${CMAKE_CURRENT_SOURCE_DIR}/../FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ALLEGRO_o1_v02.xml --runType=batch -G -N=1 --outputFile=testALLEGRO_o1_v02.root ) SET_TESTS_PROPERTIES( t_${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "Exception;EXCEPTION;ERROR;Error" ) +#-------------------------------------------------- +# test for ALLEGRO o1 v03 +SET( test_name "test_ALLEGRO_o1_v03" ) +ADD_TEST( t_${test_name} "${CMAKE_INSTALL_PREFIX}/bin/run_test_${PackageName}.sh" + ddsim --compactFile=${CMAKE_CURRENT_SOURCE_DIR}/../FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03.xml --runType=batch -G -N=1 --outputFile=testALLEGRO_o1_v03.root ) +SET_TESTS_PROPERTIES( t_${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "Exception;EXCEPTION;ERROR;Error" ) + #-------------------------------------------------- # test for ARC o1 v01 SET( test_name "test_ARC_o1_v01_run" ) From b3395c3e94c6946866a790c467c42d561122905b Mon Sep 17 00:00:00 2001 From: Zhibo WU Date: Thu, 21 Mar 2024 11:37:23 +0100 Subject: [PATCH 22/42] Add funnctions of crosstalk neighbour finding --- .../include/detectorCommon/xtalk_k4geo.h | 56 ++++ detectorCommon/src/xtalk_k4geo.cpp | 245 ++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 detectorCommon/include/detectorCommon/xtalk_k4geo.h create mode 100644 detectorCommon/src/xtalk_k4geo.cpp diff --git a/detectorCommon/include/detectorCommon/xtalk_k4geo.h b/detectorCommon/include/detectorCommon/xtalk_k4geo.h new file mode 100644 index 000000000..09c67402c --- /dev/null +++ b/detectorCommon/include/detectorCommon/xtalk_k4geo.h @@ -0,0 +1,56 @@ +#ifndef DETECTORCOMMON_XTALK_H +#define DETECTORCOMMON_XTALK_H + +// k4geo +#include "detectorSegmentations/FCCSWGridPhiEta_k4geo.h" +#include "detectorSegmentations/FCCSWGridPhiTheta_k4geo.h" +#include "detectorSegmentations/FCCSWGridModuleThetaMerged_k4geo.h" + +// DD4hep +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/Segmentations.h" +#include "DDSegmentation/BitFieldCoder.h" +// Include GridPhiEta from dd4hep once eta calculation is fixed +//#include "DDSegmentation/GridPhiEta.h" +#include "DDSegmentation/CartesianGridXY.h" +#include "DDSegmentation/CartesianGridXYZ.h" +#include "DDSegmentation/PolarGridRPhi.h" + +// Geant +#include "G4Step.hh" + +// CLHEP +#include "CLHEP/Vector/ThreeVector.h" + +#include "TGeoManager.h" + +/** Given a XML element with several daughters with the same name, e.g. + + this method returns the first daughter of type nodeName whose attribute has a given value + e.g. returns when called with (detector, "layer", "name", "1") */ +namespace det { +namespace xtalk { + + /** Special version of the crosstalk neighbours function for the readout with module and theta merged cells + * Compared to the standard version, it needs a reference to the segmentation class to + * access the number of merged cells per layer. The other parameters and return value are the same + * @param[in] aSeg Reference to the segmentation object. + * @param[in] aDecoder Handle to the bitfield decoder. + * @param[in] aFieldNames Names of the fields for which neighbours are found. + * @param[in] aFieldExtremes Minimal and maximal values for the fields. + * @param[in] aCellId ID of cell. + * return Vector of neighbours and cross talk coefficients. + */ +std::vector> xtalk_neighbours_ModuleThetaMerged(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, + const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, + const std::vector& aFieldNames, + const std::vector>>& aFieldExtremes, + uint64_t aCellId); +// debug: return cell position +std::vector xtalk_get_cell_position(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, + const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, + const std::vector& aFieldNames, + uint64_t aCellId); +} +} +#endif /* DETCOMMON_XTALK_H */ diff --git a/detectorCommon/src/xtalk_k4geo.cpp b/detectorCommon/src/xtalk_k4geo.cpp new file mode 100644 index 000000000..421670e50 --- /dev/null +++ b/detectorCommon/src/xtalk_k4geo.cpp @@ -0,0 +1,245 @@ +#include "detectorCommon/DetUtils_k4geo.h" +#include "detectorCommon/xtalk_k4geo.h" + +// DD4hep +#include "DDG4/Geant4Mapping.h" +#include "DDG4/Geant4VolumeManager.h" + +// Geant +#include "G4NavigationHistory.hh" + +// ROOT +#include "TGeoBBox.h" + +#ifdef HAVE_GEANT4_UNITS +#define MM_2_CM 1.0 +#else +#define MM_2_CM 0.1 +#endif + +#include + +#include + +namespace det { +namespace xtalk { + +// use it for module-theta merged readout (FCCSWGridModuleThetaMerged_k4geo) +std::vector> xtalk_neighbours_ModuleThetaMerged(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, + const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, + const std::vector& aFieldNames, + const std::vector>>& aFieldExtremes_layer, + uint64_t aCellId) { + + std::vector> xtalk_neighbours; + + // check that field names and extremes have the proper length + if (aFieldNames.size() != 3 || aFieldExtremes_layer[0].size()!=3) { + std::cout << "ERROR: the vectors aFieldNames and aFieldSizes should be of length = 3, corresponding to the theta/module/layer fields" << std::endl; + std::cout << "ERROR: will return empty neighbour map" << std::endl; + return xtalk_neighbours; + } + // find index of layer, module and theta in the field name vector + int idModuleField(-1); + int idThetaField(-1); + int idLayerField(-1); + for (uint itField = 0; itField < aFieldNames.size(); itField++) { + if (aFieldNames[itField] == aSeg.fieldNameModule()) + idModuleField = (int) itField; + else if (aFieldNames[itField] == aSeg.fieldNameTheta()) + idThetaField = (int) itField; + else if (aFieldNames[itField] == aSeg.fieldNameLayer()) + idLayerField = (int) itField; + + } + if (idModuleField < 0) { + std::cout << "WARNING: module field " << aSeg.fieldNameModule() << " not found in aFieldNames vector" << std::endl; + std::cout << "WARNING: will return empty neighbour map" << std::endl; + return xtalk_neighbours; + } + if (idThetaField < 0) { + std::cout << "WARNING: theta field " << aSeg.fieldNameTheta() << " not found in aFieldNames vector" << std::endl; + std::cout << "WARNING: will return empty neighbour map" << std::endl; + return xtalk_neighbours; + } + if (idLayerField < 0) { + std::cout << "WARNING: layer field " << aSeg.fieldNameLayer() << " not found in aFieldNames vector" << std::endl; + std::cout << "WARNING: will return empty neighbour map" << std::endl; + return xtalk_neighbours; + } + + double dummy_xtalk=0; + double dummy_xtalk_radial=0.35; // type 1 + double dummy_xtalk_theta=0.25; // type 2 + double dummy_xtalk_diagonal=0.05; // type 3 + double dummy_xtalk_tower=0.15; // type 4 + + // retrieve layer/module/theta of cell under study + int layer_id = aDecoder.get(aCellId, aFieldNames[idLayerField]); + //int module_id = aDecoder.get(aCellId, aFieldNames[idModuleField]); + int theta_id = aDecoder.get(aCellId, aFieldNames[idThetaField]); + + int layer_indice_offset = layer_id - aFieldExtremes_layer[0][idLayerField].first; + + // now find crosstalk neighbours + dd4hep::DDSegmentation::CellID cID = aCellId; + + // for neighbours across different layers, we have to take into + // account that merging along module and/or theta could be different + // so one cell in layer N could be neighbour to several in layer N+-1 + // The cells are classified in a different way whether they are + // direct neighbours (common surface), diagonal neighbours (common edge or vertex) + // or neither. + // To decide this, we need to check how the cells are related in both directions: + // neighbours (edge at least partially in common), diagonal neigbours (common vertex), + // none + for (int deltaLayer = -1; deltaLayer<2; deltaLayer+=2) { + + // no neighbours in layer N-1 for innermost layer + if (layer_id == aFieldExtremes_layer[layer_indice_offset][idLayerField].first && deltaLayer<0) continue; + // and in layer N+1 for outermost layer + if (layer_id == aFieldExtremes_layer[layer_indice_offset][idLayerField].second && deltaLayer>0) continue; + + // set layer field of neighbour cell + aDecoder.set(cID, aSeg.fieldNameLayer(), layer_id + deltaLayer); + + // find the neighbour(s) in module and theta + // if the numbers of module (theta) merged cells across 2 layers are the + // same then we just take the same module (theta) ID + // otherwise, we need to do some math to account for the different mergings + // note: even if number of merged cells in layer-1 is larger, a cell + // in layer could neighbour more than one cell in layer-1 if the merged + // cells are not aligned, for example if cells are grouped by 3 in a layer + // and by 4 in the next one, cell 435 in the former (which groups together + // 435-436-437) will be neighbour to cells 432 and 436 of the latter + // this might introduce duplicates, we will remove them later + // another issue is that it could add spurious cells beyond the maximum module number + // to prevent this we would need to know the max module number in layer -1 + // which would require modifying this function passing the extrema for all layers + // instead of the extrema only for a certain layer + // this border effect is also present in the original method.. + for (int i=-1; i <= aSeg.mergedThetaCells(layer_id); i++) { + int theta_id_neighbour = (theta_id + i) - ((theta_id + i) % aSeg.mergedThetaCells(layer_id+deltaLayer)); + // Do we need to check if the index neighbour theta is valid? + if (theta_id_neighbour >= theta_id && theta_id_neighbour < (theta_id + aSeg.mergedThetaCells(layer_id))) { // crosstalk neighbour type 1 + dummy_xtalk = dummy_xtalk_radial; + } + else if (theta_id_neighbour < theta_id && theta_id_neighbour > (theta_id - aSeg.mergedThetaCells(layer_id+deltaLayer))) { // crosstalk neighbour type 1 + dummy_xtalk = dummy_xtalk_radial; + } + else if (theta_id_neighbour == (theta_id + aSeg.mergedThetaCells(layer_id))) { // crosstalk neighbour type 3 + dummy_xtalk = dummy_xtalk_diagonal; + } + else if (theta_id_neighbour == (theta_id - aSeg.mergedThetaCells(layer_id+deltaLayer))) { // crosstalk neighbour type 3 + dummy_xtalk = dummy_xtalk_diagonal; + } + else continue; + + // check if neighbour theta index is valid + if (theta_id_neighbour < aFieldExtremes_layer[layer_indice_offset + deltaLayer][idThetaField].first || theta_id_neighbour > aFieldExtremes_layer[layer_indice_offset + deltaLayer][idThetaField].second) continue; + aDecoder.set(cID, aSeg.fieldNameTheta(), theta_id_neighbour); + xtalk_neighbours.emplace_back(std::make_pair(cID, dummy_xtalk)); + } + } + + // cross talk neighbour type 2 + // for neighbours in module/theta direction at same layer_id, do +-nMergedCells instead of +-1 + // reset cellID + aDecoder.set(cID, aSeg.fieldNameLayer(), layer_id); + aDecoder.set(cID, aSeg.fieldNameTheta(), theta_id); + // loop over theta cells + for (int i=-1; i<=1; i+=2) { + // calculate theta_id of neighbour + int theta_id_neighbour = theta_id + i*aSeg.mergedThetaCells(layer_id); + // check if it is within the theta range of the layer + if ( + (theta_id_neighbour < aFieldExtremes_layer[layer_indice_offset][idThetaField].first) || + (theta_id_neighbour > aFieldExtremes_layer[layer_indice_offset][idThetaField].second) + ) continue; + // set theta_id of cell ID + aDecoder[aSeg.fieldNameTheta()].set(cID, theta_id + i*aSeg.mergedThetaCells(layer_id)); + xtalk_neighbours.emplace_back(std::make_pair(cID, dummy_xtalk_theta)); + } + + // cross talk type 4 + // reset cellID + aDecoder.set(cID, aSeg.fieldNameLayer(), layer_id); + aDecoder.set(cID, aSeg.fieldNameTheta(), theta_id); + for (int loopLayer = aFieldExtremes_layer[0][idLayerField].first; loopLayer<=aFieldExtremes_layer[0][idLayerField].second; loopLayer++) { + // cells in adjacent layers have been studied, skip + if ((loopLayer - layer_id) <= 1 && (loopLayer - layer_id) >= -1) continue; + aDecoder.set(cID, aSeg.fieldNameLayer(), loopLayer); + int loopLayer_indice_offset = loopLayer - aFieldExtremes_layer[0][idLayerField].first; + // find crosstalk neighbours in the same theta tower + for (int i=-1; i <= aSeg.mergedThetaCells(layer_id); i++) { + int theta_id_neighbour = (theta_id + i) - ((theta_id + i) % aSeg.mergedThetaCells(loopLayer)); + // check if the neighbour theta index is valid + if (theta_id_neighbour >= theta_id && theta_id_neighbour < (theta_id + aSeg.mergedThetaCells(layer_id)) && theta_id_neighbour>=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].first && theta_id_neighbour<=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].second) { // crosstalk neighbour type 4 + dummy_xtalk = dummy_xtalk_tower; + aDecoder.set(cID, aSeg.fieldNameTheta(), theta_id_neighbour); + xtalk_neighbours.emplace_back(std::make_pair(cID, dummy_xtalk)); + } + else if (theta_id_neighbour < theta_id && theta_id_neighbour > (theta_id - aSeg.mergedThetaCells(loopLayer)) && theta_id_neighbour>=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].first && theta_id_neighbour<=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].second) { // crosstalk neighbour type 4 + dummy_xtalk = dummy_xtalk_tower; + aDecoder.set(cID, aSeg.fieldNameTheta(), theta_id_neighbour); + xtalk_neighbours.emplace_back(std::make_pair(cID, dummy_xtalk)); + } + else continue; + } + } + + // remove duplicates + std::vector sort_neighbours; + std::vector> new_neighbours; + for (auto &i : xtalk_neighbours) + { + bool IsNewNeighbour=true; + for (unsigned int i_loop=0; i_loop xtalk_get_cell_position(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, + const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, + const std::vector& aFieldNames, + uint64_t aCellId) { + + // find index of layer, module and theta in the field names vector + int idModuleField(-1); + int idThetaField(-1); + int idLayerField(-1); + for (uint itField = 0; itField < aFieldNames.size(); itField++) { + if (aFieldNames[itField] == aSeg.fieldNameModule()) + idModuleField = (int) itField; + else if (aFieldNames[itField] == aSeg.fieldNameTheta()) + idThetaField = (int) itField; + else if (aFieldNames[itField] == aSeg.fieldNameLayer()) + idLayerField = (int) itField; + } + // retrieve layer/module/theta of the cell under study + int layer_id = aDecoder.get(aCellId, aFieldNames[idLayerField]); + int module_id = aDecoder.get(aCellId, aFieldNames[idModuleField]); + int theta_id = aDecoder.get(aCellId, aFieldNames[idThetaField]); + std::vector cell_position; + cell_position.emplace_back(layer_id); + cell_position.emplace_back(module_id); + cell_position.emplace_back(theta_id); + return cell_position; +} + +} +} From 20a61b94a393404609893ad71b42a919b9f56684 Mon Sep 17 00:00:00 2001 From: zwu0922 Date: Tue, 16 Apr 2024 14:09:59 +0200 Subject: [PATCH 23/42] Change file names --- ...neighbors_moduleThetaMergedSegmentation.h} | 6 +++--- ...ighbors_moduleThetaMergedSegmentation.cpp} | 20 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) rename detectorCommon/include/detectorCommon/{xtalk_k4geo.h => xtalk_neighbors_moduleThetaMergedSegmentation.h} (94%) rename detectorCommon/src/{xtalk_k4geo.cpp => xtalk_neighbors_moduleThetaMergedSegmentation.cpp} (95%) diff --git a/detectorCommon/include/detectorCommon/xtalk_k4geo.h b/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h similarity index 94% rename from detectorCommon/include/detectorCommon/xtalk_k4geo.h rename to detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h index 09c67402c..4d577e568 100644 --- a/detectorCommon/include/detectorCommon/xtalk_k4geo.h +++ b/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h @@ -1,5 +1,5 @@ -#ifndef DETECTORCOMMON_XTALK_H -#define DETECTORCOMMON_XTALK_H +#ifndef DETECTORCOMMON_XTALKMODULETHETAMERGED_H +#define DETECTORCOMMON_XTALKMODULETHETAMERGED_H // k4geo #include "detectorSegmentations/FCCSWGridPhiEta_k4geo.h" @@ -53,4 +53,4 @@ std::vector xtalk_get_cell_position(const dd4hep::DDSegmentation::FCCSWGrid uint64_t aCellId); } } -#endif /* DETCOMMON_XTALK_H */ +#endif /* DETCOMMON_XTALKMODULETHETAMERGED_H */ diff --git a/detectorCommon/src/xtalk_k4geo.cpp b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp similarity index 95% rename from detectorCommon/src/xtalk_k4geo.cpp rename to detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp index 421670e50..f2a8d658c 100644 --- a/detectorCommon/src/xtalk_k4geo.cpp +++ b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp @@ -1,5 +1,5 @@ #include "detectorCommon/DetUtils_k4geo.h" -#include "detectorCommon/xtalk_k4geo.h" +#include "detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h" // DD4hep #include "DDG4/Geant4Mapping.h" @@ -43,13 +43,13 @@ std::vector> xtalk_neighbours_ModuleThetaMerged(cons int idModuleField(-1); int idThetaField(-1); int idLayerField(-1); - for (uint itField = 0; itField < aFieldNames.size(); itField++) { + for (int itField = 0; itField < aFieldNames.size(); itField++) { if (aFieldNames[itField] == aSeg.fieldNameModule()) - idModuleField = (int) itField; + idModuleField = itField; else if (aFieldNames[itField] == aSeg.fieldNameTheta()) - idThetaField = (int) itField; + idThetaField = itField; else if (aFieldNames[itField] == aSeg.fieldNameLayer()) - idLayerField = (int) itField; + idLayerField = itField; } if (idModuleField < 0) { @@ -172,7 +172,7 @@ std::vector> xtalk_neighbours_ModuleThetaMerged(cons int loopLayer_indice_offset = loopLayer - aFieldExtremes_layer[0][idLayerField].first; // find crosstalk neighbours in the same theta tower for (int i=-1; i <= aSeg.mergedThetaCells(layer_id); i++) { - int theta_id_neighbour = (theta_id + i) - ((theta_id + i) % aSeg.mergedThetaCells(loopLayer)); + int theta_id_neighbour = (theta_id + i) - ((theta_id + i) % (aSeg.mergedThetaCells(loopLayer) ? aSeg.mergedThetaCells(loopLayer):1) ); // check if the neighbour theta index is valid if (theta_id_neighbour >= theta_id && theta_id_neighbour < (theta_id + aSeg.mergedThetaCells(layer_id)) && theta_id_neighbour>=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].first && theta_id_neighbour<=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].second) { // crosstalk neighbour type 4 dummy_xtalk = dummy_xtalk_tower; @@ -222,13 +222,13 @@ std::vector xtalk_get_cell_position(const dd4hep::DDSegmentation::FCCSWGrid int idModuleField(-1); int idThetaField(-1); int idLayerField(-1); - for (uint itField = 0; itField < aFieldNames.size(); itField++) { + for (int itField = 0; itField < aFieldNames.size(); itField++) { if (aFieldNames[itField] == aSeg.fieldNameModule()) - idModuleField = (int) itField; + idModuleField = itField; else if (aFieldNames[itField] == aSeg.fieldNameTheta()) - idThetaField = (int) itField; + idThetaField = itField; else if (aFieldNames[itField] == aSeg.fieldNameLayer()) - idLayerField = (int) itField; + idLayerField = itField; } // retrieve layer/module/theta of the cell under study int layer_id = aDecoder.get(aCellId, aFieldNames[idLayerField]); From 397e3e4b6cee073124768d7026fd39fc17f586fd Mon Sep 17 00:00:00 2001 From: zwu0922 Date: Tue, 16 Apr 2024 14:19:30 +0200 Subject: [PATCH 24/42] remove possible 0 denominator --- .../src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp index f2a8d658c..f5b4d4fe8 100644 --- a/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp +++ b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp @@ -119,7 +119,7 @@ std::vector> xtalk_neighbours_ModuleThetaMerged(cons // instead of the extrema only for a certain layer // this border effect is also present in the original method.. for (int i=-1; i <= aSeg.mergedThetaCells(layer_id); i++) { - int theta_id_neighbour = (theta_id + i) - ((theta_id + i) % aSeg.mergedThetaCells(layer_id+deltaLayer)); + int theta_id_neighbour = (theta_id + i) - ((theta_id + i) % (aSeg.mergedThetaCells(layer_id+deltaLayer) ? aSeg.mergedThetaCells(layer_id+deltaLayer):1) ); // Do we need to check if the index neighbour theta is valid? if (theta_id_neighbour >= theta_id && theta_id_neighbour < (theta_id + aSeg.mergedThetaCells(layer_id))) { // crosstalk neighbour type 1 dummy_xtalk = dummy_xtalk_radial; From 1b83568f488d4bae8c2a6c8f693b797863e32063 Mon Sep 17 00:00:00 2001 From: zwu0922 Date: Wed, 17 Apr 2024 10:31:10 +0200 Subject: [PATCH 25/42] clean up comments --- ...lk_neighbors_moduleThetaMergedSegmentation.h | 17 +++++++---------- ..._neighbors_moduleThetaMergedSegmentation.cpp | 2 +- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h b/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h index 4d577e568..2441463a5 100644 --- a/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h +++ b/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h @@ -24,29 +24,26 @@ #include "TGeoManager.h" -/** Given a XML element with several daughters with the same name, e.g. - - this method returns the first daughter of type nodeName whose attribute has a given value - e.g. returns when called with (detector, "layer", "name", "1") */ namespace det { namespace xtalk { - /** Special version of the crosstalk neighbours function for the readout with module and theta merged cells - * Compared to the standard version, it needs a reference to the segmentation class to - * access the number of merged cells per layer. The other parameters and return value are the same + /** The crosstalk neighbours finding function for the readout with module and theta merged cells + * Compared to the `neighbours` function from DetUtils, it needs a reference to the segmentation class to + * access the number of merged cells per layer. The input parameters and return value are the following: * @param[in] aSeg Reference to the segmentation object. * @param[in] aDecoder Handle to the bitfield decoder. - * @param[in] aFieldNames Names of the fields for which neighbours are found. + * @param[in] aFieldNames Names of the fields for which crosstalk neighbours are found. * @param[in] aFieldExtremes Minimal and maximal values for the fields. * @param[in] aCellId ID of cell. - * return Vector of neighbours and cross talk coefficients. + * return Vector of neighbours andcross talk coefficients. */ std::vector> xtalk_neighbours_ModuleThetaMerged(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, const std::vector& aFieldNames, const std::vector>>& aFieldExtremes, uint64_t aCellId); -// debug: return cell position + +// debug: return cell layer/module/theta indices std::vector xtalk_get_cell_position(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, const std::vector& aFieldNames, diff --git a/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp index f5b4d4fe8..d35f8e87e 100644 --- a/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp +++ b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp @@ -212,7 +212,7 @@ std::vector> xtalk_neighbours_ModuleThetaMerged(cons return xtalk_neighbours; } -// return cell position, a function used for debug purpose +// return indices of layer/module/theta fields of a give cell. This is a function to be used for debug purpose std::vector xtalk_get_cell_position(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, const std::vector& aFieldNames, From 4001c3631d07453762c30556f92c8bf38ea290ee Mon Sep 17 00:00:00 2001 From: zwu0922 Date: Wed, 17 Apr 2024 11:56:42 +0200 Subject: [PATCH 26/42] change function name: xtalk_get_cell_indices --- .../xtalk_neighbors_moduleThetaMergedSegmentation.h | 2 +- ...xtalk_neighbors_moduleThetaMergedSegmentation.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h b/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h index 2441463a5..52a735aea 100644 --- a/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h +++ b/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h @@ -44,7 +44,7 @@ std::vector> xtalk_neighbours_ModuleThetaMerged(cons uint64_t aCellId); // debug: return cell layer/module/theta indices -std::vector xtalk_get_cell_position(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, +std::vector xtalk_get_cell_indices(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, const std::vector& aFieldNames, uint64_t aCellId); diff --git a/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp index d35f8e87e..10019fedd 100644 --- a/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp +++ b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp @@ -213,7 +213,7 @@ std::vector> xtalk_neighbours_ModuleThetaMerged(cons } // return indices of layer/module/theta fields of a give cell. This is a function to be used for debug purpose -std::vector xtalk_get_cell_position(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, +std::vector xtalk_get_cell_indices(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, const std::vector& aFieldNames, uint64_t aCellId) { @@ -234,11 +234,11 @@ std::vector xtalk_get_cell_position(const dd4hep::DDSegmentation::FCCSWGrid int layer_id = aDecoder.get(aCellId, aFieldNames[idLayerField]); int module_id = aDecoder.get(aCellId, aFieldNames[idModuleField]); int theta_id = aDecoder.get(aCellId, aFieldNames[idThetaField]); - std::vector cell_position; - cell_position.emplace_back(layer_id); - cell_position.emplace_back(module_id); - cell_position.emplace_back(theta_id); - return cell_position; + std::vector cell_indices; + cell_indices.emplace_back(layer_id); + cell_indices.emplace_back(module_id); + cell_indices.emplace_back(theta_id); + return cell_indices; } } From d7ba48d80f48b2b1ee620833fdbab4351f7054ea Mon Sep 17 00:00:00 2001 From: zwu0922 Date: Thu, 18 Apr 2024 11:18:14 +0200 Subject: [PATCH 27/42] Cleaning-up and improvements --- ..._neighbors_moduleThetaMergedSegmentation.h | 21 ++------ ...eighbors_moduleThetaMergedSegmentation.cpp | 51 ++++++------------- 2 files changed, 18 insertions(+), 54 deletions(-) diff --git a/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h b/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h index 52a735aea..07bce091d 100644 --- a/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h +++ b/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h @@ -2,30 +2,15 @@ #define DETECTORCOMMON_XTALKMODULETHETAMERGED_H // k4geo -#include "detectorSegmentations/FCCSWGridPhiEta_k4geo.h" -#include "detectorSegmentations/FCCSWGridPhiTheta_k4geo.h" #include "detectorSegmentations/FCCSWGridModuleThetaMerged_k4geo.h" // DD4hep #include "DD4hep/DetFactoryHelper.h" #include "DD4hep/Segmentations.h" #include "DDSegmentation/BitFieldCoder.h" -// Include GridPhiEta from dd4hep once eta calculation is fixed -//#include "DDSegmentation/GridPhiEta.h" -#include "DDSegmentation/CartesianGridXY.h" -#include "DDSegmentation/CartesianGridXYZ.h" -#include "DDSegmentation/PolarGridRPhi.h" - -// Geant -#include "G4Step.hh" - -// CLHEP -#include "CLHEP/Vector/ThreeVector.h" - -#include "TGeoManager.h" namespace det { -namespace xtalk { +namespace crosstalk { /** The crosstalk neighbours finding function for the readout with module and theta merged cells * Compared to the `neighbours` function from DetUtils, it needs a reference to the segmentation class to @@ -37,14 +22,14 @@ namespace xtalk { * @param[in] aCellId ID of cell. * return Vector of neighbours andcross talk coefficients. */ -std::vector> xtalk_neighbours_ModuleThetaMerged(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, +std::vector> getNeighboursModuleThetaMerged(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, const std::vector& aFieldNames, const std::vector>>& aFieldExtremes, uint64_t aCellId); // debug: return cell layer/module/theta indices -std::vector xtalk_get_cell_indices(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, +std::vector getCellIndices(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, const std::vector& aFieldNames, uint64_t aCellId); diff --git a/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp index 10019fedd..e43fcc596 100644 --- a/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp +++ b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp @@ -5,27 +5,15 @@ #include "DDG4/Geant4Mapping.h" #include "DDG4/Geant4VolumeManager.h" -// Geant -#include "G4NavigationHistory.hh" - -// ROOT -#include "TGeoBBox.h" - -#ifdef HAVE_GEANT4_UNITS -#define MM_2_CM 1.0 -#else -#define MM_2_CM 0.1 -#endif - #include #include namespace det { -namespace xtalk { +namespace crosstalk { // use it for module-theta merged readout (FCCSWGridModuleThetaMerged_k4geo) -std::vector> xtalk_neighbours_ModuleThetaMerged(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, +std::vector> getNeighboursModuleThetaMerged(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, const std::vector& aFieldNames, const std::vector>>& aFieldExtremes_layer, @@ -69,10 +57,10 @@ std::vector> xtalk_neighbours_ModuleThetaMerged(cons } double dummy_xtalk=0; - double dummy_xtalk_radial=0.35; // type 1 - double dummy_xtalk_theta=0.25; // type 2 - double dummy_xtalk_diagonal=0.05; // type 3 - double dummy_xtalk_tower=0.15; // type 4 + double dummy_xtalk_radial=0.7e-2; // type 1 + double dummy_xtalk_theta=0.2e-2; // type 2 + double dummy_xtalk_diagonal=0.04e-2; // type 3 + double dummy_xtalk_tower=0.1e-2; // type 4 // retrieve layer/module/theta of cell under study int layer_id = aDecoder.get(aCellId, aFieldNames[idLayerField]); @@ -121,16 +109,10 @@ std::vector> xtalk_neighbours_ModuleThetaMerged(cons for (int i=-1; i <= aSeg.mergedThetaCells(layer_id); i++) { int theta_id_neighbour = (theta_id + i) - ((theta_id + i) % (aSeg.mergedThetaCells(layer_id+deltaLayer) ? aSeg.mergedThetaCells(layer_id+deltaLayer):1) ); // Do we need to check if the index neighbour theta is valid? - if (theta_id_neighbour >= theta_id && theta_id_neighbour < (theta_id + aSeg.mergedThetaCells(layer_id))) { // crosstalk neighbour type 1 + if ((theta_id_neighbour >= theta_id && theta_id_neighbour < (theta_id + aSeg.mergedThetaCells(layer_id))) or (theta_id_neighbour < theta_id && theta_id_neighbour > (theta_id - aSeg.mergedThetaCells(layer_id+deltaLayer)))) { // crosstalk neighbour type 1 dummy_xtalk = dummy_xtalk_radial; } - else if (theta_id_neighbour < theta_id && theta_id_neighbour > (theta_id - aSeg.mergedThetaCells(layer_id+deltaLayer))) { // crosstalk neighbour type 1 - dummy_xtalk = dummy_xtalk_radial; - } - else if (theta_id_neighbour == (theta_id + aSeg.mergedThetaCells(layer_id))) { // crosstalk neighbour type 3 - dummy_xtalk = dummy_xtalk_diagonal; - } - else if (theta_id_neighbour == (theta_id - aSeg.mergedThetaCells(layer_id+deltaLayer))) { // crosstalk neighbour type 3 + else if ((theta_id_neighbour == (theta_id + aSeg.mergedThetaCells(layer_id))) or (theta_id_neighbour == (theta_id - aSeg.mergedThetaCells(layer_id+deltaLayer)))) { // crosstalk neighbour type 3 dummy_xtalk = dummy_xtalk_diagonal; } else continue; @@ -138,7 +120,7 @@ std::vector> xtalk_neighbours_ModuleThetaMerged(cons // check if neighbour theta index is valid if (theta_id_neighbour < aFieldExtremes_layer[layer_indice_offset + deltaLayer][idThetaField].first || theta_id_neighbour > aFieldExtremes_layer[layer_indice_offset + deltaLayer][idThetaField].second) continue; aDecoder.set(cID, aSeg.fieldNameTheta(), theta_id_neighbour); - xtalk_neighbours.emplace_back(std::make_pair(cID, dummy_xtalk)); + xtalk_neighbours.emplace_back(cID, dummy_xtalk); } } @@ -158,7 +140,7 @@ std::vector> xtalk_neighbours_ModuleThetaMerged(cons ) continue; // set theta_id of cell ID aDecoder[aSeg.fieldNameTheta()].set(cID, theta_id + i*aSeg.mergedThetaCells(layer_id)); - xtalk_neighbours.emplace_back(std::make_pair(cID, dummy_xtalk_theta)); + xtalk_neighbours.emplace_back(cID, dummy_xtalk_theta); } // cross talk type 4 @@ -177,12 +159,12 @@ std::vector> xtalk_neighbours_ModuleThetaMerged(cons if (theta_id_neighbour >= theta_id && theta_id_neighbour < (theta_id + aSeg.mergedThetaCells(layer_id)) && theta_id_neighbour>=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].first && theta_id_neighbour<=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].second) { // crosstalk neighbour type 4 dummy_xtalk = dummy_xtalk_tower; aDecoder.set(cID, aSeg.fieldNameTheta(), theta_id_neighbour); - xtalk_neighbours.emplace_back(std::make_pair(cID, dummy_xtalk)); + xtalk_neighbours.emplace_back(cID, dummy_xtalk); } else if (theta_id_neighbour < theta_id && theta_id_neighbour > (theta_id - aSeg.mergedThetaCells(loopLayer)) && theta_id_neighbour>=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].first && theta_id_neighbour<=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].second) { // crosstalk neighbour type 4 dummy_xtalk = dummy_xtalk_tower; aDecoder.set(cID, aSeg.fieldNameTheta(), theta_id_neighbour); - xtalk_neighbours.emplace_back(std::make_pair(cID, dummy_xtalk)); + xtalk_neighbours.emplace_back(cID, dummy_xtalk); } else continue; } @@ -199,6 +181,7 @@ std::vector> xtalk_neighbours_ModuleThetaMerged(cons if (sort_neighbours[i_loop]==i.first) { IsNewNeighbour=false; + break; } } if (IsNewNeighbour) @@ -213,7 +196,7 @@ std::vector> xtalk_neighbours_ModuleThetaMerged(cons } // return indices of layer/module/theta fields of a give cell. This is a function to be used for debug purpose -std::vector xtalk_get_cell_indices(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, +std::vector getCellIndices(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, const std::vector& aFieldNames, uint64_t aCellId) { @@ -234,11 +217,7 @@ std::vector xtalk_get_cell_indices(const dd4hep::DDSegmentation::FCCSWGridM int layer_id = aDecoder.get(aCellId, aFieldNames[idLayerField]); int module_id = aDecoder.get(aCellId, aFieldNames[idModuleField]); int theta_id = aDecoder.get(aCellId, aFieldNames[idThetaField]); - std::vector cell_indices; - cell_indices.emplace_back(layer_id); - cell_indices.emplace_back(module_id); - cell_indices.emplace_back(theta_id); - return cell_indices; + return {layer_id, module_id, theta_id}; } } From d18d3f475fe452d2ca85eb6d3c9477c16df0da94 Mon Sep 17 00:00:00 2001 From: zwu0922 Date: Thu, 18 Apr 2024 14:02:49 +0200 Subject: [PATCH 28/42] Clarify crosstalk coefficients --- ..._neighbors_moduleThetaMergedSegmentation.h | 2 +- ...eighbors_moduleThetaMergedSegmentation.cpp | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h b/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h index 07bce091d..51e910497 100644 --- a/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h +++ b/detectorCommon/include/detectorCommon/xtalk_neighbors_moduleThetaMergedSegmentation.h @@ -20,7 +20,7 @@ namespace crosstalk { * @param[in] aFieldNames Names of the fields for which crosstalk neighbours are found. * @param[in] aFieldExtremes Minimal and maximal values for the fields. * @param[in] aCellId ID of cell. - * return Vector of neighbours andcross talk coefficients. + * return Vector of neighbours and their crosstalk coefficients. */ std::vector> getNeighboursModuleThetaMerged(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, diff --git a/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp index e43fcc596..19c3d441d 100644 --- a/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp +++ b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp @@ -55,12 +55,13 @@ std::vector> getNeighboursModuleThetaMerged(const dd std::cout << "WARNING: will return empty neighbour map" << std::endl; return xtalk_neighbours; } - - double dummy_xtalk=0; - double dummy_xtalk_radial=0.7e-2; // type 1 - double dummy_xtalk_theta=0.2e-2; // type 2 - double dummy_xtalk_diagonal=0.04e-2; // type 3 - double dummy_xtalk_tower=0.1e-2; // type 4 + + // crosstalk coefficients + // also see https://indico.cern.ch/event/1368231/contributions/5904291/ + double dummy_xtalk_radial = 0.7e-2; // type 1 + double dummy_xtalk_theta = 0.2e-2; // type 2 + double dummy_xtalk_diagonal = 0.04e-2; // type 3 + double dummy_xtalk_tower = 0.1e-2; // type 4 // retrieve layer/module/theta of cell under study int layer_id = aDecoder.get(aCellId, aFieldNames[idLayerField]); @@ -107,6 +108,7 @@ std::vector> getNeighboursModuleThetaMerged(const dd // instead of the extrema only for a certain layer // this border effect is also present in the original method.. for (int i=-1; i <= aSeg.mergedThetaCells(layer_id); i++) { + double dummy_xtalk = 0.0; // will be set to the crosstalk coefficient for this neighbour, either radial or diagonal int theta_id_neighbour = (theta_id + i) - ((theta_id + i) % (aSeg.mergedThetaCells(layer_id+deltaLayer) ? aSeg.mergedThetaCells(layer_id+deltaLayer):1) ); // Do we need to check if the index neighbour theta is valid? if ((theta_id_neighbour >= theta_id && theta_id_neighbour < (theta_id + aSeg.mergedThetaCells(layer_id))) or (theta_id_neighbour < theta_id && theta_id_neighbour > (theta_id - aSeg.mergedThetaCells(layer_id+deltaLayer)))) { // crosstalk neighbour type 1 @@ -157,14 +159,12 @@ std::vector> getNeighboursModuleThetaMerged(const dd int theta_id_neighbour = (theta_id + i) - ((theta_id + i) % (aSeg.mergedThetaCells(loopLayer) ? aSeg.mergedThetaCells(loopLayer):1) ); // check if the neighbour theta index is valid if (theta_id_neighbour >= theta_id && theta_id_neighbour < (theta_id + aSeg.mergedThetaCells(layer_id)) && theta_id_neighbour>=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].first && theta_id_neighbour<=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].second) { // crosstalk neighbour type 4 - dummy_xtalk = dummy_xtalk_tower; aDecoder.set(cID, aSeg.fieldNameTheta(), theta_id_neighbour); - xtalk_neighbours.emplace_back(cID, dummy_xtalk); + xtalk_neighbours.emplace_back(cID, dummy_xtalk_tower); } else if (theta_id_neighbour < theta_id && theta_id_neighbour > (theta_id - aSeg.mergedThetaCells(loopLayer)) && theta_id_neighbour>=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].first && theta_id_neighbour<=aFieldExtremes_layer[loopLayer_indice_offset][idThetaField].second) { // crosstalk neighbour type 4 - dummy_xtalk = dummy_xtalk_tower; aDecoder.set(cID, aSeg.fieldNameTheta(), theta_id_neighbour); - xtalk_neighbours.emplace_back(cID, dummy_xtalk); + xtalk_neighbours.emplace_back(cID, dummy_xtalk_tower); } else continue; } From 871d63cd5073da54930c3a6474c3d2baccf93b09 Mon Sep 17 00:00:00 2001 From: jmcarcell Date: Tue, 23 Apr 2024 21:09:00 +0200 Subject: [PATCH 29/42] Update build workflow. Previous commit: Clarify crosstalk coefficients --- .github/workflows/key4hep-build.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/key4hep-build.yaml b/.github/workflows/key4hep-build.yaml index 5ba768a48..2acf17468 100644 --- a/.github/workflows/key4hep-build.yaml +++ b/.github/workflows/key4hep-build.yaml @@ -1,3 +1,6 @@ +# Do not edit this file, it will be overwritten! +# The template file can be found in +# https://github.com/key4hep/key4hep-actions/blob/main/workflows/key4hep-build.yaml name: Key4hep build on: @@ -7,7 +10,7 @@ on: pull_request: workflow_dispatch: schedule: - - cron: '17 5 * * *' + - cron: '16 5 * * *' jobs: From ca423a0f688873378a21ea86e161b4e8c43088e3 Mon Sep 17 00:00:00 2001 From: Zhibo Wu <91186438+zwu0922@users.noreply.github.com> Date: Mon, 6 May 2024 16:15:57 +0200 Subject: [PATCH 30/42] Change the loop variable to size_t to remove the compilation warning (#334) --- .../src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp index 19c3d441d..7e4ce2397 100644 --- a/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp +++ b/detectorCommon/src/xtalk_neighbors_moduleThetaMergedSegmentation.cpp @@ -31,7 +31,7 @@ std::vector> getNeighboursModuleThetaMerged(const dd int idModuleField(-1); int idThetaField(-1); int idLayerField(-1); - for (int itField = 0; itField < aFieldNames.size(); itField++) { + for (size_t itField = 0; itField < aFieldNames.size(); itField++) { if (aFieldNames[itField] == aSeg.fieldNameModule()) idModuleField = itField; else if (aFieldNames[itField] == aSeg.fieldNameTheta()) @@ -205,7 +205,7 @@ std::vector getCellIndices(const dd4hep::DDSegmentation::FCCSWGridModuleThe int idModuleField(-1); int idThetaField(-1); int idLayerField(-1); - for (int itField = 0; itField < aFieldNames.size(); itField++) { + for (size_t itField = 0; itField < aFieldNames.size(); itField++) { if (aFieldNames[itField] == aSeg.fieldNameModule()) idModuleField = itField; else if (aFieldNames[itField] == aSeg.fieldNameTheta()) From 09987132f17bc06862354114da0daa904497c2f0 Mon Sep 17 00:00:00 2001 From: Alvaro Tolosa Delgado <114166109+atolosadelgado@users.noreply.github.com> Date: Wed, 15 May 2024 14:34:16 +0200 Subject: [PATCH 31/42] Lightweight implementation of IDEA drift chamber (#330) * New implementation of DCH, based on excel spreadsheet * refactor fill of DCH database * remove legacy comment * compact file added * new parameters added * Twisted tube as layer envelope ready to be replaced by hyperboloid * layer shape is now hyperboloid * interlayer spacing for geometry safety is reduced to 1 nm overlap test passes * segmentation in phi works overlap tests pass * Stereo (twist) angle sign is now taken into account * DCH materials detailed in a dedicated XML file Detector constructor takes material from DCH material file * Sense wire added overlap tests pass * staggering in phi placement of cells for alternating layers * thickness of wires added to XML file * Central field wire added overlap tests pass * update geometry tree comment added todo note * field wires 123 placed properly overlap test passes * field wires 45 in place overlap test passes :) * stagering of cells changed from 0.5 to 0.25 phi aperture * vessel and gas mat/vis given via XML * wire configuration now via XML overlap test pass * setup wire thickness in the XML * old commented block deleted overlap tests pass * increase version number, keep option 1 * increase version number, keep option 1 * remove old file * superlayer bitfield added * fix bug, bitfield superlayer number is now calculated properly * bitfield superlayer starts now at zero, not one * rename DCH XML file * lcgeo test added: DCH o1 v02 overlap test * tracker README expanded * Start new version of IDEA detector * refactor DCH_info class. static members removed * refactor inner and outer radius variable names, suffix _z0 removed * comment added * Missing units... Good catch by Brieuc :) * variable name for guard wire radii are renamed for clarity * IDEA compact README updated * Add note that is based on the geometry version "IDEA231026" * comments about wires added * Central field wire, side field wire, sense wire have independent material definition * pi * Replace retrieving of global parameters from dsc with Setters * Protection against neg. parameters added in Fill_DCH_info_database fcn * Replace retrieving of global parameters from dsc with Setters * Replace retrieving of global parameters from dsc with Setters * Replace retrieving of global parameters from dsc with Setters DCH_info is now independent of the dsc file * remove condition for debuging * refactor, use method to calculate the superlayer * dummy space where the extension lives refactored, to be changed for dd4hep::rec:: * refactor constexpr PI and TWOPI * operator << added to class DCH_info * class DCH_info renamed into DCH_info_struct, placed within dd4hep::rec:: the corresponding DetectorData wraper is called now DCH_info * data extension added * data extension changed from local object to pointer so the destructor is not invoked twice * separate data extension class from detector constructor ready to be upstreamed to DD4hep * comment fixed, thanks Andre! * refactor DCH_info, prefix dch_ removed from members * refactor aliases for length/angle * use alias for super/layer numbering * add region and limitset to DCH * Vessel and gas geometry parameters completely moved to DectDimensions file * Staggering in phi confirmed by expert * aesthetics * Fix typo of variable that set radius of outer ring of guard wires Guard wires are not yet implemented, but data is stored in data extension * readout bitfield changed; now layer bitfield corresponds to layer within the superlayer * refactor global variables in XML * comments added * remove reference to excel table from DCH_info documentation * inner and outer R walls are redefined * radial walls ready, bulk material of endcap to be implemented... * endcap bulk material defined to be equivalent to 5%X0 * rename DCH o2 to v2 consistently * rename vessel endcap parameters * wire material is now a mix of coating+core * comment fix * debugGeometry tag added to DCH detector constructor used in overlap test * update readme * build wires of DCH for IDEA v3 * add a test of the whole IDEA_o1_v03 please * remove legacy file * make inline only functions not defined within the class-type functions defined within the class are marked as inline by default * comment fix * fix readme * formated as CLD readme * enable other subdetectors * comment typo fixed * IDEA o1 v03 main compact file is now mirrored from latest v02 * add the following compact files to the IDEA_o1_v03 folder: Solenoid_o1_v01.xml, EndPlateAbsorber_o1_v01.xml * Add detector dimensions * use DDRec/include/DCH_info.h * IDEA v3 material compact file updated * exclude this new detector in case data extension header file is missing * Andre fix: cmake macro CHECK_INCLUDE_FILE_CXX now checks for data extension header file --- CMakeLists.txt | 11 + .../BeamInstrumentation_o1_v01.xml | 36 + .../compact/IDEA_o1_v03/Beampipe_o4_v05.xml | 158 ++++ .../DectDimensions_IDEA_o1_v02.xml | 273 ++++++ .../IDEA_o1_v03/DriftChamber_o1_v02.xml | 165 ++++ .../IDEA_o1_v03/EndPlateAbsorber_o1_v01.xml | 21 + .../IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml | 87 ++ .../compact/IDEA_o1_v03/LumiCal_o1_v01.xml | 192 ++++ .../compact/IDEA_o1_v03/Solenoid_o1_v01.xml | 50 + .../IDEA_o1_v03/Vertex_IDEA_o1_v01.xml | 726 ++++++++++++++ .../compact/IDEA_o1_v03/elements_o1_v01.xml | 884 ++++++++++++++++++ .../compact/IDEA_o1_v03/materials_o1_v02.xml | 398 ++++++++ FCCee/IDEA/compact/README.md | 18 +- detector/tracker/DriftChamber_o1_v02.cpp | 517 ++++++++++ detector/tracker/README.md | 16 + lcgeoTests/CMakeLists.txt | 19 + lcgeoTests/compact/DCH_standalone_o1_v02.xml | 195 ++++ 17 files changed, 3764 insertions(+), 2 deletions(-) create mode 100644 FCCee/IDEA/compact/IDEA_o1_v03/BeamInstrumentation_o1_v01.xml create mode 100644 FCCee/IDEA/compact/IDEA_o1_v03/Beampipe_o4_v05.xml create mode 100644 FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v02.xml create mode 100644 FCCee/IDEA/compact/IDEA_o1_v03/DriftChamber_o1_v02.xml create mode 100644 FCCee/IDEA/compact/IDEA_o1_v03/EndPlateAbsorber_o1_v01.xml create mode 100644 FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml create mode 100644 FCCee/IDEA/compact/IDEA_o1_v03/LumiCal_o1_v01.xml create mode 100644 FCCee/IDEA/compact/IDEA_o1_v03/Solenoid_o1_v01.xml create mode 100644 FCCee/IDEA/compact/IDEA_o1_v03/Vertex_IDEA_o1_v01.xml create mode 100644 FCCee/IDEA/compact/IDEA_o1_v03/elements_o1_v01.xml create mode 100644 FCCee/IDEA/compact/IDEA_o1_v03/materials_o1_v02.xml create mode 100644 detector/tracker/DriftChamber_o1_v02.cpp create mode 100644 lcgeoTests/compact/DCH_standalone_o1_v02.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index d1441d0b2..a5fc00744 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,17 @@ if(NOT K4GEO_USE_LCIO) message(STATUS "Use of LCIO is DISABLED, some detectors that depend on LCIO will not be built: ${lcio_sources}") endif() +include(CheckIncludeFileCXX) +set(CMAKE_REQUIRED_LIBRARIES DD4hep::DDRec) +CHECK_INCLUDE_FILE_CXX(DDRec/DCH_info.h DCH_INFO_H_EXIST) +set(CMAKE_REQUIRED_LIBRARIES) +set(FILES_DEPENDINGON_DCH_INFO_H "DriftChamber_o1_v02.cpp" ) + +if(NOT DCH_INFO_H_EXIST) + list(FILTER sources EXCLUDE REGEX "${FILES_DEPENDINGON_DCH_INFO_H}") + message(WARNING "Subdetector ${FILES_DEPENDINGON_DCH_INFO_H} will not be built because header file ${DCH_INFO_H} was not found") +endif() + file(GLOB G4sources ./plugins/TPCSDAction.cpp ./plugins/CaloPreShowerSDAction.cpp diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/BeamInstrumentation_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v03/BeamInstrumentation_o1_v01.xml new file mode 100644 index 000000000..49647b2b8 --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v03/BeamInstrumentation_o1_v01.xml @@ -0,0 +1,36 @@ + + + + COmpensating and screening solenoids for FCCee + + + + + Beampipe Instrumentation + + + + + + +

+ + + + + + + + +
+ +
+ + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/Beampipe_o4_v05.xml b/FCCee/IDEA/compact/IDEA_o1_v03/Beampipe_o4_v05.xml new file mode 100644 index 000000000..73283b2f5 --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v03/Beampipe_o4_v05.xml @@ -0,0 +1,158 @@ + + + + A beampipe for FCCee detector based on CLD + + + + + + + + + + + + + + + + + + + + + Part of beampipe made of AlBeMet162 and Paraffin flow + + + + + + + +
+
+
+
+ + + + + + + + + + + + Golden foil in the inner part of the Be beampipe + +
+ +
+ +
+ +
+ + +
+ +
+ +
+ +
+ +
+ + + + + +Synch Radiation mask inside the beam-pipe, at z = 2.1 m + + + +
+ +
+ +
+ + + +Full Cone Tungsten Shield + + + + Beampipe Shield (APS: WHAT????? +18 cm (??plus??) as solenoid is now closer to IP) +
+ + + + +Asymmetric Tungsten Shield no Rotation + + + + +
+ + was 370. Add 0.1*mm so that rmax1 is larger than rmin1 +
+ + one degree less, to fit lumical window +
+ +
+ + + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v02.xml b/FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v02.xml new file mode 100644 index 000000000..35ecaf11d --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v02.xml @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/DriftChamber_o1_v02.xml b/FCCee/IDEA/compact/IDEA_o1_v03/DriftChamber_o1_v02.xml new file mode 100644 index 000000000..b7f781561 --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v03/DriftChamber_o1_v02.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system:5,superlayer:5,layer:4,nphi:11,stereosign:-1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/EndPlateAbsorber_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v03/EndPlateAbsorber_o1_v01.xml new file mode 100644 index 000000000..55acb6c6d --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v03/EndPlateAbsorber_o1_v01.xml @@ -0,0 +1,21 @@ + + + + + Endcap plate absorber to mimic the material budget from the solenoid (0.75 X0) present only in the barrel and start the showers. + + + + + + + + + + + + + + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml b/FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml new file mode 100644 index 000000000..f6075a08d --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml @@ -0,0 +1,87 @@ + + + + + + + + Version o1_v03 of the IDEA detector + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/LumiCal_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v03/LumiCal_o1_v01.xml new file mode 100644 index 000000000..2c19e5772 --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v03/LumiCal_o1_v01.xml @@ -0,0 +1,192 @@ + + + + LumiCal for FCCee detector + + + + + + + + + + + system:8,barrel:3,layer:8,slice:8,r:32:-16,phi:-16 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/Solenoid_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v03/Solenoid_o1_v01.xml new file mode 100644 index 000000000..7287662e0 --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v03/Solenoid_o1_v01.xml @@ -0,0 +1,50 @@ + + + + This is a solenoid place holder. It has the right spacial extent and overall accounts for the 0.75 X0 but its internals should be revised by ultra-thin magnet designers --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/Vertex_IDEA_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v03/Vertex_IDEA_o1_v01.xml new file mode 100644 index 000000000..c38d19da7 --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v03/Vertex_IDEA_o1_v01.xml @@ -0,0 +1,726 @@ + + + + + A Vertex Detector for the FCC-ee IDEA detector concept, based on the engineered design by Fabrizio Palla and Filippo Bosi (INFN Pisa) + + Vertex detector + + + + + + + + + + + + + Vertex Assembly + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${GlobalTrackerReadoutID} + + + ${GlobalTrackerReadoutID_OB} + + + ${GlobalTrackerReadoutID_Disk} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Vertex Detector Disks + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/elements_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v03/elements_o1_v01.xml new file mode 100644 index 000000000..f35eb3454 --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v03/elements_o1_v01.xml @@ -0,0 +1,884 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/materials_o1_v02.xml b/FCCee/IDEA/compact/IDEA_o1_v03/materials_o1_v02.xml new file mode 100644 index 000000000..cdf85f605 --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v03/materials_o1_v02.xml @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CMS ECAL https://gitlab.cern.ch/geant4/geant4/-/blob/master/examples/advanced/composite_calorimeter/dataglobal/material.cms#L183 + + + + + + + + + + + + + + + + 0.98810714*2.7 + 0.011892860*10.49 + + field wire center: 50 um Al (core), 0.3 um Ag (coating) + + + + + 0.98516708*2.7 + 0.014832922*10.49 + + field wires top/bottom: 40 um Al (core), 0.3 um Ag (coating) + + + + + 0.97066175*19.28+0.029338250*19.3 + + sense wire: 20 um W (core), 0.3 um Au (coating) + + + + + + + + diff --git a/FCCee/IDEA/compact/README.md b/FCCee/IDEA/compact/README.md index 17ba793c0..fc2eb6045 100644 --- a/FCCee/IDEA/compact/README.md +++ b/FCCee/IDEA/compact/README.md @@ -1,4 +1,18 @@ IDEA ==== -IDEA_o1_v01: IDEA version picked from the latest version in FCCDetectors repo -IDEA_o1_v02: Based on o1_v01 but with a detailed description of the vertex detector and the drift chamber, a place holder solenoid and the endplate absorber. Missing: SiWrapper, calorimeter, detailed muons system (coming soon). + +IDEA_o1_v01 +------------ + +IDEA version picked from the latest version in FCCDetectors repo + +IDEA_o1_v02 +------------ + +Based on o1_v01 but with a detailed description of the vertex detector and the drift chamber, a place holder solenoid and the endplate absorber. Missing: SiWrapper, calorimeter, detailed muons system (coming soon). + +IDEA_o1_v03 +------------ + +Based on o1_v02 but replacing the drift chamber (o1, v01) for the lightweight implementation based on twisted tubes (o1, v02). Production threshold and step limit physics have to be tuned + diff --git a/detector/tracker/DriftChamber_o1_v02.cpp b/detector/tracker/DriftChamber_o1_v02.cpp new file mode 100644 index 000000000..87c54e0fd --- /dev/null +++ b/detector/tracker/DriftChamber_o1_v02.cpp @@ -0,0 +1,517 @@ +//---------------------------------- +// DCH detector v2 +//---------------------------------- + +/*! + * \brief Detector constructor of DCH v2 + * \details This code creates full geometry of IDEA DCH subdetector + * \author Alvaro Tolosa-Delgado alvaro.tolosa.delgado@cern.ch + * \author Brieuc Francois brieuc.francois@cern.ch + * \version 2 + * \date 2024 + * \pre DD4hep compiled with Geant4+Qt + */ + + +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/Shapes.h" +#include "DD4hep/Printout.h" +#include "DD4hep/Detector.h" + +#include "DDRec/DCH_info.h" + +namespace DCH_v2 { + +using DCH_length_t = dd4hep::rec::DCH_info_struct::DCH_length_t; +using DCH_angle_t = dd4hep::rec::DCH_info_struct::DCH_angle_t; +using DCH_layer = dd4hep::rec::DCH_info_struct::DCH_layer; + +/// Function to build DCH +static dd4hep::Ref_t create_DCH_o1_v02(dd4hep::Detector &desc, dd4hep::xml::Handle_t handle, dd4hep::SensitiveDetector sens) +{ + dd4hep::xml::DetElement detElem = handle; + std::string detName = detElem.nameStr(); + int detID = detElem.id(); + dd4hep::DetElement det(detName, detID); + sens.setType("tracker"); + + // initialize empty DCH_info object + // data extension mechanism requires it to be a raw pointer + dd4hep::rec::DCH_info * DCH_i = new dd4hep::rec::DCH_info(); + // fill DCH_i with information from the XML file + { + // DCH outer geometry dimensions + DCH_i->Set_rin ( desc.constantAsDouble("DCH_gas_inner_cyl_R") ); + DCH_i->Set_rout ( desc.constantAsDouble("DCH_gas_outer_cyl_R") ); + DCH_i->Set_lhalf( desc.constantAsDouble("DCH_gas_Lhalf") ); + + // guard wires position, fix position + DCH_i->Set_guard_rin_at_z0 ( desc.constantAsDouble("DCH_guard_inner_r_at_z0" ) ); + DCH_i->Set_guard_rout_at_zL2( desc.constantAsDouble("DCH_guard_outer_r_at_zL2") ); + + DCH_angle_t dch_alpha = desc.constantAsDouble("DCH_alpha"); + DCH_i->Set_twist_angle( 2*dch_alpha ); + + DCH_i->Set_nsuperlayers(desc.constantAsLong("DCH_nsuperlayers")); + DCH_i->Set_nlayersPerSuperlayer(desc.constantAsLong("DCH_nlayersPerSuperlayer")); + + DCH_i->Set_ncell0(desc.constantAsLong("DCH_ncell")); + DCH_i->Set_ncell_increment(desc.constantAsLong("DCH_ncell_increment")); + DCH_i->Set_ncell_per_sector(desc.constantAsLong("DCH_ncell_per_sector")); + + DCH_i->Set_first_width ( desc.constantAsDouble("DCH_first_width") ); + DCH_i->Set_first_sense_r( desc.constantAsDouble("DCH_first_sense_r") ); + + bool buildLayers = detElem.attr(_Unicode(buildLayers)); + if(buildLayers){ + DCH_i->BuildLayerDatabase(); + // safety check just in case something went wrong... + if( DCH_i->IsDatabaseEmpty() ) + throw std::runtime_error("Empty database"); + } + + bool printExcelTable = detElem.attr(_Unicode(printExcelTable)); + if(printExcelTable) + DCH_i->Show_DCH_info_database(std::cout); + } + + bool debugGeometry = detElem.hasChild(_Unicode(debugGeometry)); + auto gasElem = detElem.child("gas"); + auto gasvolMat = desc.material(gasElem.attr(_Unicode(material))); + auto gasvolVis = desc.visAttributes(gasElem.attr(_Unicode(vis))); + + auto vesselElem = detElem.child("vessel"); + auto vesselSkinVis = desc.visAttributes(vesselElem.attr(_Unicode(visSkin))); + auto vesselBulkVis = desc.visAttributes(vesselElem.attr(_Unicode(visBulk))); + auto vessel_mainMaterial = desc.material(vesselElem.attr(_Unicode(mainMaterial))); + auto vessel_fillmaterial_outerR = desc.material(vesselElem.attr(_Unicode(fillmaterial_outerR))); + auto vessel_fillmaterial_endcap = desc.material(vesselElem.attr(_Unicode(fillmaterial_endcap))); + DCH_length_t vessel_fillmaterial_fraction_outerR = vesselElem.attr(_Unicode(fillmaterial_fraction_outerR)) ; + DCH_length_t vessel_fillmaterial_fraction_endcap = vesselElem.attr(_Unicode(fillmaterial_fraction_endcap)) ; + + if( 0 > vessel_fillmaterial_fraction_outerR || 1 < vessel_fillmaterial_fraction_outerR ) + throw std::runtime_error("vessel_fillmaterial_fraction_outerR must be between 0 and 1"); + if( 0 > vessel_fillmaterial_fraction_endcap || 1 < vessel_fillmaterial_fraction_endcap ) + throw std::runtime_error("vessel_fillmaterial_fraction_z must be between 0 and 1"); + + auto wiresElem = detElem.child("wires"); + auto wiresVis = desc.visAttributes(wiresElem.attr(_Unicode(vis))); + bool buildSenseWires = wiresElem.attr(_Unicode(buildSenseWires)); + bool buildFieldWires = wiresElem.attr(_Unicode(buildFieldWires)); + + DCH_length_t dch_SWire_thickness = wiresElem.attr(_Unicode(SWire_thickness)) ; + DCH_length_t dch_FSideWire_thickness = wiresElem.attr(_Unicode(FSideWire_thickness)) ; + DCH_length_t dch_FCentralWire_thickness = wiresElem.attr(_Unicode(FCentralWire_thickness)) ; + + auto dch_SWire_material = desc.material(wiresElem.attr(_Unicode(SWire_material)) ) ; + auto dch_FSideWire_material = desc.material(wiresElem.attr(_Unicode(FSideWire_material)) ) ; + auto dch_FCentralWire_material = desc.material(wiresElem.attr(_Unicode(FCentralWire_material)) ) ; + + /* Geometry tree: + * Gas (tube) -> Layer_1 (hyp) -> cell_1 (twisted tube) + * -> cell_... (twisted tube) + * -> Layer_... (hyp) -> cell_1 (twisted tube) + * -> cell_... (twisted tube) + * -> Inner radius vessel wall + * -> Outer radius vessel wall -> fill made of foam + * -> Endcap disk vessel wall -> fill made of kapton + * + * Layers represent a segmentation in radius + * Sectors represent a segmentation in phi + * Each cell corresponds to a Detector Element + * Vessel wall has to be defined as 3 volumes to account for independent thickness and materials + */ + + DCH_length_t safety_r_interspace = 1 * dd4hep::nm; + DCH_length_t safety_z_interspace = 1 * dd4hep::nm; + DCH_length_t safety_phi_interspace = 1e-6 * dd4hep::rad; + + DCH_length_t vessel_thickness_innerR = desc.constantAsDouble("DCH_vessel_thickness_innerR"); + DCH_length_t vessel_thickness_outerR = desc.constantAsDouble("DCH_vessel_thickness_outerR"); + DCH_length_t vessel_endcapdisk_zmin = desc.constantAsDouble("DCH_vessel_disk_zmin"); + DCH_length_t vessel_endcapdisk_zmax = desc.constantAsDouble("DCH_vessel_disk_zmax"); + + // if( 0 > vessel_thickness_z ) + // throw std::runtime_error("vessel_thickness_z must be positive"); + if( 0 > vessel_thickness_innerR ) + throw std::runtime_error("vessel_thickness_innerR must be positive"); + if( 0 > vessel_thickness_outerR ) + throw std::runtime_error("vessel_thickness_outerR must be positive"); + + // // // // // // // // // // // // // // // + // // // // // MAIN VOLUME // // // // // // + // // // // // // // // // // // // // // // + dd4hep::Tube gas_s( DCH_i->rin - vessel_thickness_innerR, + DCH_i->rout + vessel_thickness_outerR, + vessel_endcapdisk_zmax ); + dd4hep::Volume gas_v (detName+"_gas", gas_s, gasvolMat ); + gas_v.setVisAttributes( gasvolVis ); + gas_v.setRegion ( desc, detElem.regionStr() ); + gas_v.setLimitSet( desc, detElem.limitsStr() ); + + DCH_length_t vessel_innerR_start = DCH_i->rin - vessel_thickness_innerR + safety_r_interspace; + DCH_length_t vessel_innerR_end = DCH_i->rin ; + DCH_length_t vessel_outerR_start = DCH_i->rout; + DCH_length_t vessel_outerR_end = DCH_i->rout + vessel_thickness_outerR - safety_r_interspace; + DCH_length_t vessel_R_zhalf = vessel_endcapdisk_zmax - safety_z_interspace; + // // // // // // // // // // // // // // // + // // // // // INNER R WALL // // // // // + // // // // // // // // // // // // // // // + dd4hep::Tube vessel_innerR_s( vessel_innerR_start, + vessel_innerR_end , + vessel_R_zhalf + ); + dd4hep::Volume vessel_innerR_v (detName+"_vessel_innerR", vessel_innerR_s, vessel_mainMaterial ); + vessel_innerR_v.setVisAttributes( vesselSkinVis ); + gas_v.placeVolume(vessel_innerR_v); + // // // // // // // // // // // // // // // + // // // // // OUTER R WALL // // // // // + // // // // // // // // // // // // // // // + dd4hep::Tube vessel_outerR_s( vessel_outerR_start, + vessel_outerR_end , + vessel_R_zhalf + ); + dd4hep::Volume vessel_outerR_v (detName+"_vessel_outerR", vessel_outerR_s, vessel_mainMaterial ); + vessel_outerR_v.setVisAttributes( vesselSkinVis ); + + // if thickness fraction of bulk material is defined, build the bulk material + if(0 < vessel_fillmaterial_fraction_outerR) + { + double f = vessel_fillmaterial_fraction_outerR; + DCH_length_t fillmaterial_thickness = f * (vessel_outerR_end - vessel_outerR_start); + DCH_length_t rstart = vessel_outerR_start + 0.5*(1-f)*fillmaterial_thickness; + DCH_length_t rend = vessel_outerR_end - 0.5*(1-f)*fillmaterial_thickness; + dd4hep::Tube vessel_fillmat_outerR_s( rstart, + rend , + vessel_R_zhalf - safety_z_interspace + ); + dd4hep::Volume vessel_fillmat_outerR_v (detName+"_vessel_fillmat_outerR", + vessel_fillmat_outerR_s, + vessel_fillmaterial_outerR + ); + vessel_fillmat_outerR_v.setVisAttributes( vesselBulkVis ); + vessel_outerR_v.placeVolume(vessel_fillmat_outerR_v); + } + gas_v.placeVolume(vessel_outerR_v); + + // // // // // // // // // // // // // // // + // // // // // ENDCAP WALL // // // // // + // // // // // // // // // // // // // // // + DCH_length_t vessel_endcap_thickness = vessel_endcapdisk_zmax - vessel_endcapdisk_zmin - 2*safety_z_interspace; + DCH_length_t vessel_endcap_zpos = 0.5*(vessel_endcapdisk_zmax + vessel_endcapdisk_zmin); + DCH_length_t vessel_endcap_rstart = vessel_innerR_end + safety_r_interspace; + DCH_length_t vessel_endcap_rend = vessel_outerR_start - safety_r_interspace; + dd4hep::Tube vessel_endcap_s( vessel_endcap_rstart, + vessel_endcap_rend, + 0.5*vessel_endcap_thickness + ); + dd4hep::Volume vessel_endcap_v (detName+"_vessel_endcap", vessel_endcap_s, vessel_mainMaterial ); + vessel_endcap_v.setVisAttributes( vesselSkinVis ); + + // if thickness fraction of bulk material is defined, build the bulk material + if(0 < vessel_fillmaterial_fraction_endcap) + { + double f = vessel_fillmaterial_fraction_endcap; + DCH_length_t fillmaterial_thickness = f * vessel_endcap_thickness; + dd4hep::Tube vessel_fillmat_endcap_s( vessel_endcap_rstart + safety_r_interspace, + vessel_endcap_rend - safety_r_interspace , + 0.5*fillmaterial_thickness + ); + dd4hep::Volume vessel_fillmat_endcap_v (detName+"_vessel_fillmat_endcap", + vessel_fillmat_endcap_s, + vessel_fillmaterial_endcap + ); + vessel_fillmat_endcap_v.setVisAttributes( vesselBulkVis ); + vessel_endcap_v.placeVolume(vessel_fillmat_endcap_v); + } + // place endcap wall at +/- z + gas_v.placeVolume(vessel_endcap_v, dd4hep::Position(0,0, vessel_endcap_zpos)); + gas_v.placeVolume(vessel_endcap_v, dd4hep::Position(0,0,-vessel_endcap_zpos)); + + // // // // // // // // // // // // // // // + // // // // // DCH layers // // // // // + // // // // // // // // // // // // // // // + for(const auto& [ilayer, l] : DCH_i->database ) + { + + // // // // // // // // // // // // // // // // // // // // / + // // // // // INITIALIZATION OF THE LAYER // // // // // // + // // // // // // // // // // // // // // // // // // // // + // Hyperboloid parameters: + /// inner radius at z=0 + DCH_length_t rin = l.radius_fdw_z0+safety_r_interspace; + /// inner stereoangle, calculated from rin(z=0) + DCH_angle_t stin = DCH_i->stereoangle_z0(rin); + /// outer radius at z=0 + DCH_length_t rout = l.radius_fuw_z0-safety_r_interspace; + /// outer stereoangle, calculated from rout(z=0) + DCH_angle_t stout = DCH_i->stereoangle_z0(rout); + /// half-length + DCH_length_t dz = DCH_i->Lhalf + safety_z_interspace; + + dd4hep::Hyperboloid layer_s(rin, stin, rout, stout, dz); + + + std::string layer_name = detName+"_layer"+std::to_string(ilayer); + dd4hep::Volume layer_v ( layer_name , layer_s, gasvolMat ); + layer_v.setVisAttributes( desc.visAttributes( Form("dch_layer_vis%d", ilayer%22) ) ); + auto layer_pv = gas_v.placeVolume(layer_v); + // ilayer is a counter that runs from 1 to 112 (nsuperlayers * nlayersPerSuperlayer) + // it seems more convenient to store the layer number within the superlayer + // ilayerWithinSuperlayer runs from 0 to 7 (nlayersPerSuperlayer-1) + int ilayerWithinSuperlayer = (ilayer-1) % DCH_i->nlayersPerSuperlayer; + layer_pv.addPhysVolID("layer", ilayerWithinSuperlayer ); + // add superlayer bitfield + int nsuperlayer_minus_1 = DCH_i->Get_nsuperlayer_minus_1(ilayer); + layer_pv.addPhysVolID("superlayer", nsuperlayer_minus_1 ); + + dd4hep::DetElement layer_DE(det,layer_name+"DE", ilayer); + layer_DE.setPlacement(layer_pv); + + // // // // // // // // // // // // // // // // // // // // + // // // // // SEGMENTATION OF THE LAYER // // // // // // + // // // // // INTO CELLS (TWISTED TUBES) // // // // // // + // // // // // // // // // // // // // // // // // // // // + + // ncells in this layer = 2x number of wires + int ncells = l.nwires/2; + DCH_angle_t phi_step = (TMath::TwoPi()/ncells)*dd4hep::rad; + + // unitary cell (Twisted tube) is repeated for each layer l.nwires/2 times + // Twisted tube parameters + DCH_angle_t cell_twistangle = l.StereoSign() * DCH_i->twist_angle; + DCH_length_t cell_rin_z0 = l.radius_fdw_z0 + 2*safety_r_interspace; + DCH_length_t cell_rout_z0 = l.radius_fuw_z0 - 2*safety_r_interspace; + DCH_length_t cell_rin_zLhalf = DCH_i->Radius_zLhalf(cell_rin_z0); + DCH_length_t cell_rout_zLhalf = DCH_i->Radius_zLhalf(cell_rout_z0); + DCH_length_t cell_dz = DCH_i->Lhalf; + DCH_angle_t cell_phi_width = phi_step - safety_phi_interspace; + dd4hep::TwistedTube cell_s( cell_twistangle, cell_rin_zLhalf, cell_rout_zLhalf, cell_dz, 1, cell_phi_width); + + // initialize cell volume + std::string cell_name = detName+"_layer"+std::to_string(ilayer)+"_cell"; + dd4hep::Volume cell_v (cell_name, cell_s, gasvolMat ); + cell_v.setSensitiveDetector(sens); + cell_v.setVisAttributes( desc.visAttributes( "dch_no_vis_nodaughters" ) ); + + // // // // // // // // // // // // // // // // // // // // + // // // // // // POSITIONING OF WIRES // // // // // // // + // // // // // // // // // // // // // // // // // // // // + { + // // // // // // // // // // // // // // // // // // // // + // // // // // // POSITIONING OF SENSE WIRES // // // // // + // // // // // // // // // // // // // // // // // // // // + // average radius to position sense wire + DCH_length_t cell_rave_z0 = 0.5*(cell_rin_z0+cell_rout_z0); + DCH_length_t cell_swire_radius = dch_SWire_thickness/2; + DCH_length_t swlength = 0.5*DCH_i->WireLength(ilayer,cell_rave_z0) + - cell_swire_radius*cos(DCH_i->stereoangle_z0(cell_rave_z0)) + - safety_z_interspace; + if(buildSenseWires) + { + dd4hep::Tube swire_s(0., dch_SWire_thickness, swlength); + dd4hep::Volume swire_v(cell_name+"_swire", swire_s, dch_SWire_material); + swire_v.setVisAttributes( wiresVis ); + // Change sign of stereo angle to place properly the wire inside the twisted tube + dd4hep::RotationX stereoTr( (-1.)*l.StereoSign()*DCH_i->stereoangle_z0(cell_rave_z0) ); + dd4hep::Transform3D swireTr ( stereoTr * dd4hep::Translation3D(cell_rave_z0,0.,0.) ); + cell_v.placeVolume(swire_v,swireTr); + } + if(buildFieldWires) + { + // // // // // // // // // // // // // // // // // // // // + // // // // // // POSITIONING OF FIELD WIRES // // // // // + // // // // // // // // // // // // // // // // // // // // + // + // The following sketch represents the crossection of a DCH cell, where + // O symbol = Field wires, the number in parenthesis is used as ID + // X symbol = sense wire + // + // ^ radius + // + // O(1)---O(4)---O(6) radius_z0 = l.radius_fuw_z0 == (++l).radius_fdw_z0 + // + // O(2) X O(7) radius_z0 = average(l.radius_fuw_z0, l.radius_fdw_z0) + // + // O(3)---O(5)---O(8) radius_z0 = l.radius_fdw_z0 == (--l).radius_fuw_z0 + // + // --> phi axis + // + // In the previous sketch, the wires are shared among several cells. + // Since we are using an actual shape to contain each cell, + // it is not feasible. + // + // As a workaround, we introduce an offset in phi and radially to the cell center, + // in such a manner that the wires are fully contained in one cell. + // The following code implements the following sketch: + // + // O(1)---O(4)--- radius_z0 = l.radius_fuw_z0 - wire_thickness/2 + // + // O(2) X radius_z0 = average(l.radius_fuw_z0, l.radius_fdw_z0) + // + // O(3)---O(5)--- radius_z0 = l.radius_fdw_z0 + wire_thickness/2 + // + // phi_offset(n) = atan( wire_thickness/2 / radius_z0 ) + // + // notice that the field wires are offcentered with respect to the sense wire + // by about 20um/1cm ~ 0.1 mrad, which is not expected to have any impact + + /// encapsulate the calculation of the phi offset into a function + /// since it will be different for each field wire + /// it includes the safety phi distance + auto fwire_phi_offset = [&](DCH_length_t radial_distance, DCH_length_t wire_radius)->DCH_angle_t + { + return atan(wire_radius/radial_distance)*dd4hep::rad + safety_phi_interspace; + }; + + // // // // // // // // // // // // // // // // // // // // + // // // // // // POSITIONING OF F WIRE 2 // // // // // // + // // // // // // REQUIRES OFFSET OF PHI // // // // // // + // // // // // // // // // // // // // // // // // // // // + { + DCH_length_t fwire_radius = dch_FCentralWire_thickness/2; + DCH_length_t fwire_r_z0 = cell_rave_z0; + DCH_angle_t fwire_stereo = (-1.)*l.StereoSign()*DCH_i->stereoangle_z0(fwire_r_z0); + DCH_angle_t fwire_phi = -cell_phi_width/2 + fwire_phi_offset( fwire_r_z0, fwire_radius); + DCH_length_t fwire_length = 0.5*DCH_i->WireLength(ilayer, fwire_r_z0) + - fwire_radius*cos(DCH_i->stereoangle_z0(fwire_r_z0)) + - safety_z_interspace; + + dd4hep::Tube fwire_s(0., fwire_radius, fwire_length); + dd4hep::Volume fwire_v(cell_name+"_f2wire", fwire_s, dch_FCentralWire_material ); + fwire_v.setVisAttributes( wiresVis ); + // Change sign of stereo angle to place properly the wire inside the twisted tube + dd4hep::RotationX fwireStereoTr( fwire_stereo ); + dd4hep::RotationZ fwirePhoTr( fwire_phi ); + dd4hep::Transform3D fwireTr ( fwirePhoTr * fwireStereoTr * dd4hep::Translation3D(fwire_r_z0,0.,0.) ); + cell_v.placeVolume(fwire_v,fwireTr); + } + + // // // // // // // // // // // // // // // // // // // // + // // // // // // POSITIONING OF F WIRE 1 // // // // // + // // // // // // REQUIRES OFFSET OF PHI & R // // // // // + // // // // // // // // // // // // // // // // // // // // + { + DCH_length_t fwire_radius = dch_FSideWire_thickness/2; + // decrease radial distance, move it closer to the sense wire + DCH_length_t fwire_r_z0 = cell_rout_z0 - fwire_radius; + DCH_angle_t fwire_stereo = (-1.)*l.StereoSign()*DCH_i->stereoangle_z0(fwire_r_z0); + DCH_angle_t fwire_phi = -cell_phi_width/2 + fwire_phi_offset( fwire_r_z0, fwire_radius); + DCH_length_t fwire_length = 0.5*DCH_i->WireLength(ilayer, fwire_r_z0) + - fwire_radius*cos(DCH_i->stereoangle_z0(fwire_r_z0)) + - safety_z_interspace; + + dd4hep::Tube fwire_s(0., fwire_radius, fwire_length); + dd4hep::Volume fwire_v(cell_name+"_f1wire", fwire_s, dch_FSideWire_material ); + fwire_v.setVisAttributes( wiresVis ); + // Change sign of stereo angle to place properly the wire inside the twisted tube + dd4hep::RotationX fwireStereoTr( fwire_stereo ); + dd4hep::RotationZ fwirePhoTr( fwire_phi ); + dd4hep::Transform3D fwireTr ( fwirePhoTr * fwireStereoTr * dd4hep::Translation3D(fwire_r_z0,0.,0.) ); + cell_v.placeVolume(fwire_v,fwireTr); + } + // // // // // // // // // // // // // // // // // // // // + // // // // // // POSITIONING OF F WIRE 3 // // // // // + // // // // // // REQUIRES OFFSET OF PHI & R // // // // // + // // // // // // // // // // // // // // // // // // // // + { + DCH_length_t fwire_radius = dch_FSideWire_thickness/2; + // increase radial distance, move it closer to the sense wire + DCH_length_t fwire_r_z0 = cell_rin_z0 + fwire_radius; + DCH_angle_t fwire_stereo = (-1.)*l.StereoSign()*DCH_i->stereoangle_z0(fwire_r_z0); + DCH_angle_t fwire_phi = -cell_phi_width/2 + fwire_phi_offset( fwire_r_z0, fwire_radius); + DCH_length_t fwire_length = 0.5*DCH_i->WireLength(ilayer, fwire_r_z0) + - fwire_radius*cos(DCH_i->stereoangle_z0(fwire_r_z0)) + - safety_z_interspace; + + dd4hep::Tube fwire_s(0., fwire_radius, fwire_length); + dd4hep::Volume fwire_v(cell_name+"_f3wire", fwire_s, dch_FSideWire_material ); + fwire_v.setVisAttributes( wiresVis ); + // Change sign of stereo angle to place properly the wire inside the twisted tube + dd4hep::RotationX fwireStereoTr( fwire_stereo ); + dd4hep::RotationZ fwirePhoTr( fwire_phi ); + dd4hep::Transform3D fwireTr ( fwirePhoTr * fwireStereoTr * dd4hep::Translation3D(fwire_r_z0,0.,0.) ); + cell_v.placeVolume(fwire_v,fwireTr); + } + // // // // // // // // // // // // // // // // // // // // + // // // // // // POSITIONING OF F WIRE 5 // // // // // + // // // // // // REQUIRES OFFSET OF R // // // // // + // // // // // // // // // // // // // // // // // // // // + { + DCH_length_t fwire_radius = dch_FSideWire_thickness/2; + // increase radial distance, move it closer to the sense wire + DCH_length_t fwire_r_z0 = cell_rin_z0 + fwire_radius; + DCH_angle_t fwire_stereo = (-1.)*l.StereoSign()*DCH_i->stereoangle_z0(fwire_r_z0); + DCH_length_t fwire_length = 0.5*DCH_i->WireLength(ilayer, fwire_r_z0) + - fwire_radius*cos(DCH_i->stereoangle_z0(fwire_r_z0)) + - safety_z_interspace; + + dd4hep::Tube fwire_s(0., fwire_radius, fwire_length); + dd4hep::Volume fwire_v(cell_name+"_f5wire", fwire_s, dch_FSideWire_material ); + fwire_v.setVisAttributes( wiresVis ); + // Change sign of stereo angle to place properly the wire inside the twisted tube + dd4hep::RotationX fwireStereoTr( fwire_stereo ); + dd4hep::Transform3D fwireTr ( fwireStereoTr * dd4hep::Translation3D(fwire_r_z0,0.,0.) ); + cell_v.placeVolume(fwire_v,fwireTr); + } + // // // // // // // // // // // // // // // // // // // // + // // // // // // POSITIONING OF F WIRE 4 // // // // // + // // // // // // REQUIRES OFFSET OF R // // // // // + // // // // // // // // // // // // // // // // // // // // + { + DCH_length_t fwire_radius = dch_FSideWire_thickness/2; + // increase radial distance, move it closer to the sense wire + DCH_length_t fwire_r_z0 = cell_rout_z0 - fwire_radius; + DCH_angle_t fwire_stereo = (-1.)*l.StereoSign()*DCH_i->stereoangle_z0(fwire_r_z0); + DCH_length_t fwire_length = 0.5*DCH_i->WireLength(ilayer, fwire_r_z0) + - fwire_radius*cos(DCH_i->stereoangle_z0(fwire_r_z0)) + - safety_z_interspace; + + dd4hep::Tube fwire_s(0., fwire_radius, fwire_length); + dd4hep::Volume fwire_v(cell_name+"_f4wire", fwire_s, dch_FSideWire_material ); + fwire_v.setVisAttributes( wiresVis ); + // Change sign of stereo angle to place properly the wire inside the twisted tube + dd4hep::RotationX fwireStereoTr( fwire_stereo ); + dd4hep::Transform3D fwireTr ( fwireStereoTr * dd4hep::Translation3D(fwire_r_z0,0.,0.) ); + cell_v.placeVolume(fwire_v,fwireTr); + } + }// end building field wires + }/// end building wires + int maxphi = ncells; + if(debugGeometry) + maxphi=3; + for(int nphi = 0; nphi < maxphi; ++nphi) + { + // TODO: check if staggering is just + 0.25*cell_phi_width*(ilayer%2); + // phi positioning, adding offset for odd ilayers + DCH_angle_t cell_phi_angle = phi_step * nphi + 0.25*cell_phi_width*(ilayer%2); + // conversion of RotationZ into Transform3D using constructor) + dd4hep::Transform3D cellTr { dd4hep::RotationZ(cell_phi_angle) }; + auto cell_pv = layer_v.placeVolume(cell_v, cellTr); + cell_pv.addPhysVolID("nphi", nphi); + cell_pv.addPhysVolID("stereosign", l.StereoSign() ); + + dd4hep::DetElement cell_DE(layer_DE,cell_name+std::to_string(nphi)+"DE", nphi); + cell_DE.setPlacement(cell_pv); + } + + + } + + // Place our mother volume in the world + dd4hep::Volume wVol = desc.pickMotherVolume(det); + dd4hep::PlacedVolume vessel_pv = wVol.placeVolume(gas_v); + // Associate the wall to the detector element. + det.setPlacement(vessel_pv); + // Assign the system ID to our mother volume + vessel_pv.addPhysVolID("system", detID); + det.addExtension(DCH_i); + + return det; + +} + +}; // end DCH_v2 namespace + + +DECLARE_DETELEMENT(DriftChamber_o1_v02_T, DCH_v2::create_DCH_o1_v02) diff --git a/detector/tracker/README.md b/detector/tracker/README.md index 3fbe421fc..d2e213cfe 100644 --- a/detector/tracker/README.md +++ b/detector/tracker/README.md @@ -30,3 +30,19 @@ What to improve: - better automation in the C++ to rely less on user defined parameters from the xml - better variable naming (started already but could still be improved) - make sense out of the many layer radiuses defined + + +### o1_v02 +Reimplementation of the drift chamber concept, based on a fully detailed spreadsheet. The improvements with respect the previous implementation are the following: +- The standalone simulation consumes 400MB of memory, out of which the geometry represents 150MB. +- The DCH is built out of few global parameters, thanks to the prescription given in the spreadsheet +- C++ guidelines are followed +- ASCII drawing is included to make sense of positioning of wires inside the cells +- The cell shape corresponds to a twisted tube, which is missing in ROOT, but DD4hep provides a workaround +- Because of the previous point, this subdetector can not be used by any ROOT-based application, and the shape parameters can be accessed only by DD4hep/Geant4 +- Visualization of the full DCH is possible with Geant4+Qt, but not with ROOT-based applications +- The optional tag `` build only 3 sectors of each layer, it must be used only when checking for overlaps. +- Endcap services. A dummy plate with 5% X0 is used to account for such services. +- Vessel wall is a sandwich of Carbon fiber and PE foam. The thickness of the fill material is given as a fraction of the total thickness of the wall. It is adjusted to provide 1.2%X0 radially and 5%X0 longitudinally. +- Material of field and sense wire is averaged for the sake of speedup. +- Guard wires are not implemented yet. diff --git a/lcgeoTests/CMakeLists.txt b/lcgeoTests/CMakeLists.txt index 59dac77fa..93cd303a8 100644 --- a/lcgeoTests/CMakeLists.txt +++ b/lcgeoTests/CMakeLists.txt @@ -86,6 +86,15 @@ ADD_TEST( t_${test_name} "${CMAKE_INSTALL_PREFIX}/bin/run_test_${PackageName}.sh ddsim --compactFile=${CMAKE_CURRENT_SOURCE_DIR}/../FCCee/IDEA/compact/IDEA_o1_v02/IDEA_o1_v02.xml --runType=batch -G -N=1 --outputFile=testIDEA_o1_v02.slcio ) SET_TESTS_PROPERTIES( t_${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "Exception;EXCEPTION;ERROR;Error" TIMEOUT 360) +#-------------------------------------------------- +# test for IDEA o1 v03 +if(DCH_INFO_H_EXIST) +SET( test_name "test_IDEA_o1_v03" ) +ADD_TEST( t_${test_name} "${CMAKE_INSTALL_PREFIX}/bin/run_test_${PackageName}.sh" + ddsim --compactFile=${CMAKE_CURRENT_SOURCE_DIR}/../FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml --runType=batch -G -N=1 --outputFile=testIDEA_o1_v03.slcio ) +SET_TESTS_PROPERTIES( t_${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "Exception;EXCEPTION;ERROR;Error" TIMEOUT 700) +endif() + #-------------------------------------------------- # test for ALLEGRO o1 v02 SET( test_name "test_ALLEGRO_o1_v02" ) @@ -114,6 +123,16 @@ ADD_TEST( t_${test_name} "${CMAKE_INSTALL_PREFIX}/bin/run_test_${PackageName}.sh SET_TESTS_PROPERTIES( t_${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "Exception;EXCEPTION;ERROR;Error" ) set_tests_properties( t_${test_name} PROPERTIES TIMEOUT 360) +#-------------------------------------------------- +# test for DCH o1 v02 +if(DCH_INFO_H_EXIST) +SET( test_name "test_DCH_o1_v02_overlap" ) +ADD_TEST( t_${test_name} "${CMAKE_INSTALL_PREFIX}/bin/run_test_${PackageName}.sh" + ddsim --compactFile=${CMAKE_CURRENT_SOURCE_DIR}/compact/DCH_standalone_o1_v02.xml --runType run --part.userParticleHandler= --macroFile=${CMAKE_CURRENT_SOURCE_DIR}/../utils/overlap.mac ) +SET_TESTS_PROPERTIES( t_${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "Exception;EXCEPTION;ERROR;Error" ) +set_tests_properties( t_${test_name} PROPERTIES TIMEOUT 60) +endif() + #-------------------------------------------------- ADD_EXECUTABLE( TestSensThickness src/TestSensThickness.cpp ) diff --git a/lcgeoTests/compact/DCH_standalone_o1_v02.xml b/lcgeoTests/compact/DCH_standalone_o1_v02.xml new file mode 100644 index 000000000..93a3ec357 --- /dev/null +++ b/lcgeoTests/compact/DCH_standalone_o1_v02.xml @@ -0,0 +1,195 @@ + + + + The compact format of the DCH subdetector, built from XLSX spreadsheet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system:5,superlayer:5,layer:4,nphi:11,stereosign:-1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 20439a8b2fcd03e02fffaa045bbad4cf5354bff7 Mon Sep 17 00:00:00 2001 From: jmcarcell Date: Mon, 27 May 2024 22:10:47 +0200 Subject: [PATCH 32/42] Don't build on CentOS 7. Previous commit: Lightweight implementation of IDEA drift chamber (#330) --- .github/workflows/key4hep-build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/key4hep-build.yaml b/.github/workflows/key4hep-build.yaml index 2acf17468..f0bcb2c11 100644 --- a/.github/workflows/key4hep-build.yaml +++ b/.github/workflows/key4hep-build.yaml @@ -18,7 +18,7 @@ jobs: strategy: matrix: build_type: ["release", "nightly"] - image: ["alma9", "ubuntu22", "centos7"] + image: ["alma9", "ubuntu22"] fail-fast: false runs-on: ubuntu-latest steps: From e5d641abaf68ff0354bcc646842931fd0ee2f79d Mon Sep 17 00:00:00 2001 From: Brieuc Francois Date: Thu, 30 May 2024 10:38:33 +0200 Subject: [PATCH 33/42] [IDEA] Fix solenoid for o1_v03 (#335) --- ...ions_IDEA_o1_v02.xml => DectDimensions_IDEA_o1_v03.xml} | 6 ------ FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml | 7 ++++--- 2 files changed, 4 insertions(+), 9 deletions(-) rename FCCee/IDEA/compact/IDEA_o1_v03/{DectDimensions_IDEA_o1_v02.xml => DectDimensions_IDEA_o1_v03.xml} (98%) diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v02.xml b/FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v03.xml similarity index 98% rename from FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v02.xml rename to FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v03.xml index 35ecaf11d..f3779cf19 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v02.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v03.xml @@ -145,12 +145,6 @@ - - - - - - diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml b/FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml index f6075a08d..ff2bbf3db 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml @@ -31,7 +31,7 @@ - + @@ -59,14 +59,15 @@ + + - Date: Thu, 6 Jun 2024 17:17:15 +0200 Subject: [PATCH 34/42] ALLEGRO_o1_v03: VTX and drift chamber from IDEA, add magnetic fields (#339) * [FCCee-ALLEGRO] Take the vertex and drift chamber from IDEA * Only one master xml to maintain for ALLEGRO_o1_v03 * Add magnetic field to ALLEGRO_o1_v03 * Fix tests for stable stack --- .../compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03.xml | 75 +++++- .../ALLEGRO_o1_v03_ecalonly.xml | 36 --- .../ALLEGRO_o1_v03_trackeronly.xml | 40 --- .../compact/ALLEGRO_o1_v03/DectDimensions.xml | 72 +++--- .../compact/ALLEGRO_o1_v03/DriftChamber.xml | 110 -------- .../ALLEGRO_o1_v03/DriftChamber_o1_v02.xml | 1 + .../ALLEGRO_o1_v03/Solenoid_o1_v01_02.xml | 57 ----- .../ALLEGRO/compact/ALLEGRO_o1_v03/Vertex.xml | 234 ------------------ .../ALLEGRO_o1_v03/Vertex_IDEA_o1_v01.xml | 1 + .../compact/ALLEGRO_o1_v03/materials.xml | 121 ++++++++- FCCee/ALLEGRO/compact/README.md | 6 +- lcgeoTests/CMakeLists.txt | 2 + 12 files changed, 236 insertions(+), 519 deletions(-) delete mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_ecalonly.xml delete mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_trackeronly.xml delete mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DriftChamber.xml create mode 120000 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DriftChamber_o1_v02.xml delete mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Solenoid_o1_v01_02.xml delete mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Vertex.xml create mode 120000 FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Vertex_IDEA_o1_v01.xml diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03.xml index 16a7139ef..da8377bfd 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03.xml @@ -33,14 +33,79 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_ecalonly.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_ecalonly.xml deleted file mode 100644 index 01add4188..000000000 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_ecalonly.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - Master compact file describing the latest developments of the FCCee ALLEGRO detector concept. - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_trackeronly.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_trackeronly.xml deleted file mode 100644 index d1150548a..000000000 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03_trackeronly.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - Master compact file describing the latest developments of the FCCee ALLEGRO detector concept. - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DectDimensions.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DectDimensions.xml index 237223204..7b3a2a305 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DectDimensions.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DectDimensions.xml @@ -18,15 +18,18 @@ - - + + + + + - + - - - + + + @@ -54,11 +57,6 @@ - - - - - @@ -72,22 +70,24 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + @@ -130,6 +130,7 @@ + @@ -182,11 +183,17 @@ + + + + + + + - - + + - @@ -197,8 +204,11 @@ - - + + + + + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DriftChamber.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DriftChamber.xml deleted file mode 100644 index b24fa784f..000000000 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DriftChamber.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - - Detector description for the IDEA Drift Chamber. To understand the free parameters below, look e.g. at https://indico.cern.ch/event/932973/contributions/4041314/attachments/2139657/3664808/primavera_FCCworkshop_2020.pdf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - system:4,superLayer:5,layer:5,phi:11,hitorigin:3,stereo:1,layerInCell:2 - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DriftChamber_o1_v02.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DriftChamber_o1_v02.xml new file mode 120000 index 000000000..90e9942c5 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/DriftChamber_o1_v02.xml @@ -0,0 +1 @@ +../../../IDEA/compact/IDEA_o1_v03/DriftChamber_o1_v02.xml \ No newline at end of file diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Solenoid_o1_v01_02.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Solenoid_o1_v01_02.xml deleted file mode 100644 index 69a117f86..000000000 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Solenoid_o1_v01_02.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - Solenoid - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Vertex.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Vertex.xml deleted file mode 100644 index a28449d6f..000000000 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Vertex.xml +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - CLD Vertex Detector for FCCee - - - Tracking detectors - - - - - - - - - - - - Vertex Assembly - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${GlobalTrackerReadoutID} - - - ${GlobalTrackerReadoutID} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Vertex Detector Endcaps - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Vertex_IDEA_o1_v01.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Vertex_IDEA_o1_v01.xml new file mode 120000 index 000000000..cfab0871b --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/Vertex_IDEA_o1_v01.xml @@ -0,0 +1 @@ +../../../IDEA/compact/IDEA_o1_v03/Vertex_IDEA_o1_v01.xml \ No newline at end of file diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/materials.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/materials.xml index 7fe008147..d2cec5087 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/materials.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/materials.xml @@ -104,12 +104,12 @@ - + - + @@ -118,14 +118,14 @@ - + - + @@ -206,6 +206,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CMS ECAL https://gitlab.cern.ch/geant4/geant4/-/blob/master/examples/advanced/composite_calorimeter/dataglobal/material.cms#L183 + + + + + + + + + + + + + + + + 0.98810714*2.7 + 0.011892860*10.49 + + field wire center: 50 um Al (core), 0.3 um Ag (coating) + + + + + + 0.98516708*2.7 + 0.014832922*10.49 + + field wires top/bottom: 40 um Al (core), 0.3 um Ag (coating) + + + + + + 0.97066175*19.28+0.029338250*19.3 + + sense wire: 20 um W (core), 0.3 um Au (coating) + + + + + + diff --git a/FCCee/ALLEGRO/compact/README.md b/FCCee/ALLEGRO/compact/README.md index 94f9ac59c..630ebcbdb 100644 --- a/FCCee/ALLEGRO/compact/README.md +++ b/FCCee/ALLEGRO/compact/README.md @@ -2,8 +2,10 @@ ALLEGRO ======================== ALLEGRO_o1_v01: it is a liquid Noble gas based detector. This version picked from the latest version in FCCDetectors repo. -ALLEGRO_o1_v02: evolves from o1_v01, replacing the barrel ECAL and adding a detailed version drift chamber. +ALLEGRO_o1_v02: evolves from o1_v01, replacing the barrel ECAL and adding a detailed version drift chamber. This version has a constant cell size in theta for the ECAL barrel (instead of eta as in o1_v01) and now it is possible to have a different number of cells merged for each longitudinal layer. Known caveat: the drift chamber has a larger z extent than in the IDEA detector but the wire spacing was not re-optimized. It is ok software-wise but the currently implemented design is not fully compliant with R&D considerations, will need a new drift chamber layout from the detector concept team. -ALLEGRO_o1_v03: with respect to v02 it features an ECal barrel with 11 layers and cell corners projective along phi +ALLEGRO_o1_v03: with respect to v02 it features an ECal barrel with 11 layers and cell corners projective along phi. +The vertex detector and drift chamber are now taken directly from IDEA_o1_v03, this effectively updates both the vertex detector (which was taken from an old CLD version) and the drift chamber (which was corresponding to IDEA_o1_v02/DriftChamber_o1_v01.xml). The z-extent of the drift chamber is now unchanged w.r.t. the IDEA detector (2 m) since it requires optimization anyway. +Magnetic fields (solenoid + MDI) have been added. diff --git a/lcgeoTests/CMakeLists.txt b/lcgeoTests/CMakeLists.txt index 93cd303a8..83aae7aa0 100644 --- a/lcgeoTests/CMakeLists.txt +++ b/lcgeoTests/CMakeLists.txt @@ -104,10 +104,12 @@ SET_TESTS_PROPERTIES( t_${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "Except #-------------------------------------------------- # test for ALLEGRO o1 v03 +if(DCH_INFO_H_EXIST) SET( test_name "test_ALLEGRO_o1_v03" ) ADD_TEST( t_${test_name} "${CMAKE_INSTALL_PREFIX}/bin/run_test_${PackageName}.sh" ddsim --compactFile=${CMAKE_CURRENT_SOURCE_DIR}/../FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ALLEGRO_o1_v03.xml --runType=batch -G -N=1 --outputFile=testALLEGRO_o1_v03.root ) SET_TESTS_PROPERTIES( t_${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "Exception;EXCEPTION;ERROR;Error" ) +endif() #-------------------------------------------------- # test for ARC o1 v01 From 3042e58fe481d7f6ced84641ceaaaac9a0cc661d Mon Sep 17 00:00:00 2001 From: Frank Gaede Date: Mon, 10 Jun 2024 14:50:41 +0200 Subject: [PATCH 35/42] Fix event display for tracker endcap in CEDViewer (#333) * fix nPetals in ZDiskPetalsData (for CEDViewer) * Make sure petalNumber and sensorsPerPetal are filled correctly everywhere --------- Co-authored-by: tmadlener --- detector/tracker/SiTrackerEndcap_o2_v01ext_geo.cpp | 6 +++++- detector/tracker/SiTrackerEndcap_o2_v02ext_geo.cpp | 8 ++++++-- detector/tracker/TrackerEndcap_o1_v04_geo.cpp | 9 ++++++--- detector/tracker/TrackerEndcap_o1_v05_geo.cpp | 5 ++++- detector/tracker/TrackerEndcap_o2_v04_geo.cpp | 8 ++++++-- detector/tracker/TrackerEndcap_o2_v05_geo.cpp | 8 ++++++-- detector/tracker/TrackerEndcap_o2_v06_geo.cpp | 8 ++++++-- 7 files changed, 39 insertions(+), 13 deletions(-) diff --git a/detector/tracker/SiTrackerEndcap_o2_v01ext_geo.cpp b/detector/tracker/SiTrackerEndcap_o2_v01ext_geo.cpp index 490b0c4b1..4c89750d5 100644 --- a/detector/tracker/SiTrackerEndcap_o2_v01ext_geo.cpp +++ b/detector/tracker/SiTrackerEndcap_o2_v01ext_geo.cpp @@ -111,6 +111,7 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s int l_id = x_layer.id(); int mod_num = 0; int ring_num = 0; + int petal_num = 0; double sumZ(0.), innerR(1e100), outerR(0.); @@ -135,6 +136,8 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s sumZ += zstart; r = r + mod_shape->GetDY(); + petal_num = nmodules; // store the module number of this ring for nPetals in ZDiskPetalsData + for(int k=0; klayers.push_back(thisLayer); } diff --git a/detector/tracker/SiTrackerEndcap_o2_v02ext_geo.cpp b/detector/tracker/SiTrackerEndcap_o2_v02ext_geo.cpp index 812db1bb3..37b26cac6 100644 --- a/detector/tracker/SiTrackerEndcap_o2_v02ext_geo.cpp +++ b/detector/tracker/SiTrackerEndcap_o2_v02ext_geo.cpp @@ -126,6 +126,7 @@ static Ref_t create_detector(Detector& theDetector,xml_h e,SensitiveDetector sen int l_id=x_layer.id(); int mod_num=0; int ring_num=0; + int petal_num=0; double sumZ(0.),innerR(1e100),outerR(0.); //loop only to count the number of rings in a disk - it is then needed for looking for neighborous when you are in a "border" cell int nrings = 0; @@ -155,7 +156,9 @@ static Ref_t create_detector(Detector& theDetector,xml_h e,SensitiveDetector sen outerR=r+mod_shape->GetDZ(); sumZ+=zstart; r=r+mod_shape->GetDY(); - + + petal_num = nmodules; // store the module number of this ring for nPetals in ZDiskPetalsData + for(int k=0;klayers.push_back(thisLayer); } diff --git a/detector/tracker/TrackerEndcap_o1_v04_geo.cpp b/detector/tracker/TrackerEndcap_o1_v04_geo.cpp index cbc66d2d4..d39566be9 100644 --- a/detector/tracker/TrackerEndcap_o1_v04_geo.cpp +++ b/detector/tracker/TrackerEndcap_o1_v04_geo.cpp @@ -123,6 +123,7 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s int l_id = x_layer.id(); int mod_num = 0; int ring_no=0; + int petal_num = 0; //Cannot handle rings in ZDiskPetalsData, calculate approximate petal quantities double sumZ(0.), innerR(1e100),outerR(0.); @@ -151,8 +152,9 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s outerR = r + mod_shape->GetDZ(); sumZ+=zstart; - - + + petal_num = nmodules; // store the module number of this ring for nPetals in ZDiskPetalsData + //NOTE: As in the barrel, what we call "module" in the xml is like a single trapezoidal wafer //For reasons of bit conservation in the encoding and to be more similar to the ILD geometry //A module has to be something that consists of many "sensors" (wafers) @@ -199,7 +201,8 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s thisLayer.zPosition= sumZ/ring_no; //calc average z thisLayer.distanceSensitive = innerR ; thisLayer.lengthSensitive = outerR-innerR; - thisLayer.petalNumber = ring_no ; //Store the number of rings in petalNumber needed for tracking + thisLayer.petalNumber = petal_num; + thisLayer.sensorsPerPetal = ring_no ; //Store the number of rings in petalNumber needed for tracking //this assumes there is a constant sensitive thickness even though //the layer could have different modules with different thicknesses diff --git a/detector/tracker/TrackerEndcap_o1_v05_geo.cpp b/detector/tracker/TrackerEndcap_o1_v05_geo.cpp index 73934e5e5..6e3b892b6 100644 --- a/detector/tracker/TrackerEndcap_o1_v05_geo.cpp +++ b/detector/tracker/TrackerEndcap_o1_v05_geo.cpp @@ -138,6 +138,7 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s int l_id = x_layer.id(); int mod_num = 0; int ring_no=0; + int petal_num=0; //Cannot handle rings in ZDiskPetalsData, calculate approximate petal quantities double sumZ(0.), innerR(1e100),outerR(0.); @@ -173,6 +174,7 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s sumZ+=zstart; + petal_num = nmodules; // store the module number of this ring for nPetals in ZDiskPetalsData //NOTE: As in the barrel, what we call "module" in the xml is like a single trapezoidal wafer //For reasons of bit conservation in the encoding and to be more similar to the ILD geometry @@ -288,7 +290,8 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s thisLayer.zPosition= sumZ/ring_no; //calc average z thisLayer.distanceSensitive = innerR ; thisLayer.lengthSensitive = outerR-innerR; - thisLayer.petalNumber = ring_no ; //Store the number of rings in petalNumber needed for tracking + thisLayer.petalNumber = petal_num; + thisLayer.sensorsPerPetal = ring_no ; //Store the number of rings in petalNumber needed for tracking //this assumes there is a constant sensitive thickness even though //the layer could have different modules with different thicknesses diff --git a/detector/tracker/TrackerEndcap_o2_v04_geo.cpp b/detector/tracker/TrackerEndcap_o2_v04_geo.cpp index c84c93829..8178551b0 100644 --- a/detector/tracker/TrackerEndcap_o2_v04_geo.cpp +++ b/detector/tracker/TrackerEndcap_o2_v04_geo.cpp @@ -125,6 +125,7 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s int l_id = x_layer.id(); int mod_num = 0; int ring_no=0; + int petal_num = 0; //Cannot handle rings in ZDiskPetalsData, calculate approximate petal quantities double sumZ(0.), innerR(1e100),outerR(0.); double sensitiveThickness(0.0); @@ -155,7 +156,9 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s sumZ+=zstart; r=r+mod_shape->GetDY(); - + + petal_num = nmodules; // store the module number of this ring for nPetals in ZDiskPetalsData + //NOTE: As in the barrel, what we call "module" in the xml is like a single trapezoidal wafer //For reasons of bit conservation in the encoding and to be more similar to the ILD geometry //A module has to be something that consists of many "sensors" (wafers) @@ -202,7 +205,8 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s thisLayer.zPosition= sumZ/ring_no; //calc average z thisLayer.distanceSensitive = innerR ; thisLayer.lengthSensitive = outerR-innerR; - thisLayer.petalNumber = ring_no ; //Store the number of rings in petalNumber needed for tracking + thisLayer.petalNumber = petal_num; + thisLayer.sensorsPerPetal = ring_no ; //Store the number of rings in petalNumber needed for tracking //this assumes there is a constant sensitive thickness even though //the layer could have different modules with different thicknesses diff --git a/detector/tracker/TrackerEndcap_o2_v05_geo.cpp b/detector/tracker/TrackerEndcap_o2_v05_geo.cpp index 2910756fa..fa12598e5 100644 --- a/detector/tracker/TrackerEndcap_o2_v05_geo.cpp +++ b/detector/tracker/TrackerEndcap_o2_v05_geo.cpp @@ -140,6 +140,7 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s int l_id = x_layer.id(); int mod_num = 0; int ring_no=0; + int petal_num = 0; //Cannot handle rings in ZDiskPetalsData, calculate approximate petal quantities double sumZ(0.), innerR(1e100),outerR(0.); double sensitiveThickness(0.0); @@ -176,12 +177,14 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s sumZ+=zstart; r=r+mod_shape->GetDY(); + + petal_num = nmodules; // store the module number of this ring for nPetals in ZDiskPetalsData //NOTE: As in the barrel, what we call "module" in the xml is like a single trapezoidal wafer //For reasons of bit conservation in the encoding and to be more similar to the ILD geometry //A module has to be something that consists of many "sensors" (wafers) //We chose to do it so one phi-ring is one module. i.e. Modules have constant R - + for(int k=0; kGetDY(); - + + petal_num = nmodules ; // store the module number of this ring for nPetals in ZDiskPetalsData + //NOTE: As in the barrel, what we call "module" in the xml is like a single trapezoidal wafer //For reasons of bit conservation in the encoding and to be more similar to the ILD geometry //A module has to be something that consists of many "sensors" (wafers) @@ -308,7 +311,8 @@ static Ref_t create_detector(Detector& theDetector, xml_h e, SensitiveDetector s thisLayer.zPosition= sumZ/ring_no; //calc average z thisLayer.distanceSensitive = innerR ; thisLayer.lengthSensitive = outerR-innerR; - thisLayer.petalNumber = ring_no ; //Store the number of rings in petalNumber needed for tracking + thisLayer.petalNumber = petal_num ; // module number is the number of petals - needed for CED event display + thisLayer.sensorsPerPetal = ring_no ; //Store the number of rings as sensors per petal - needed for tracking //this assumes there is a constant sensitive thickness even though //the layer could have different modules with different thicknesses From 07fa4d069fc582133acf950ce91180243ec66eed Mon Sep 17 00:00:00 2001 From: jmcarcell Date: Tue, 11 Jun 2024 20:22:38 +0200 Subject: [PATCH 36/42] Remove a CentOS7 workflow using the CLIC nightlies --- .github/workflows/linux.yml | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 .github/workflows/linux.yml diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml deleted file mode 100644 index 8efe1f35c..000000000 --- a/.github/workflows/linux.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: linux -on: [push, pull_request] - -jobs: - centos7: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - COMPILER: [gcc11] - LCG: [104] - - steps: - - uses: actions/checkout@v3 - - uses: cvmfs-contrib/github-action-cvmfs@v3 - - uses: aidasoft/run-lcg-view@v4 - with: - view-path: "/cvmfs/clicdp.cern.ch/iLCSoft/lcg/${{ matrix.LCG }}/nightly/x86_64-centos7-${{ matrix.COMPILER }}-opt" - setup-script: "init_ilcsoft.sh" - run: | - mkdir build - cd build - cmake -GNinja -C ${ILCSOFT}/ILCSoft.cmake -DCMAKE_CXX_FLAGS=" -fdiagnostics-color=always " .. - ninja -k0 - ninja install - ctest --output-on-failure From 77e501e47007088f1770eb7009cf1b3684b009f1 Mon Sep 17 00:00:00 2001 From: Juan Miguel Carceller <22276694+jmcarcell@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:50:34 +0200 Subject: [PATCH 37/42] Delete an unused string (#342) --- detector/calorimeter/CaloEndcapDiscs_o1_v01_geo.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/detector/calorimeter/CaloEndcapDiscs_o1_v01_geo.cpp b/detector/calorimeter/CaloEndcapDiscs_o1_v01_geo.cpp index e363f4468..8b4790fe2 100644 --- a/detector/calorimeter/CaloEndcapDiscs_o1_v01_geo.cpp +++ b/detector/calorimeter/CaloEndcapDiscs_o1_v01_geo.cpp @@ -4,7 +4,6 @@ #define endmsg std::endl #define lLog std::cout namespace MSG { -const std::string ERROR = " Error: "; const std::string DEBUG = " Debug: "; const std::string INFO = " Info: "; } From 5bb9d75fb3cfa25fca340d4822fae5970b8056cb Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Fri, 28 Jun 2024 10:38:55 +0200 Subject: [PATCH 38/42] Make TPC have detector ID 4 and use consistent tracker cell ID (#343) --- ILD/compact/ILD_l5_v11/FCCdefs.xml | 2 +- ILD/compact/ILD_l5_v11/basic_defs.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ILD/compact/ILD_l5_v11/FCCdefs.xml b/ILD/compact/ILD_l5_v11/FCCdefs.xml index ef934c4e1..b91d6bd68 100644 --- a/ILD/compact/ILD_l5_v11/FCCdefs.xml +++ b/ILD/compact/ILD_l5_v11/FCCdefs.xml @@ -104,6 +104,6 @@ - + diff --git a/ILD/compact/ILD_l5_v11/basic_defs.xml b/ILD/compact/ILD_l5_v11/basic_defs.xml index 31fba57e2..afbac9bfd 100644 --- a/ILD/compact/ILD_l5_v11/basic_defs.xml +++ b/ILD/compact/ILD_l5_v11/basic_defs.xml @@ -8,14 +8,14 @@ - + - + From 829873090103740451fab48a8291eee6c8c900c1 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori <39376142+giovannimarchiori@users.noreply.github.com> Date: Thu, 4 Jul 2024 11:21:51 +0200 Subject: [PATCH 39/42] fix detector type in ALLEGRO v03 ECAL calibration scripts (#349) --- .../ECalBarrel_thetamodulemerged_calibration.xml | 4 ++-- .../ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_upstream.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_calibration.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_calibration.xml index d36f28b06..e3e45f658 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_calibration.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_calibration.xml @@ -92,7 +92,7 @@ - + @@ -149,7 +149,7 @@ - + diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_upstream.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_upstream.xml index bc37473bd..31ea25fa0 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_upstream.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v03/ECalBarrel_thetamodulemerged_upstream.xml @@ -92,7 +92,7 @@ - + @@ -154,4 +154,4 @@ - + \ No newline at end of file From 8c1f7f6ed55ff51cb9e301b651a4bf0f91460835 Mon Sep 17 00:00:00 2001 From: Juan Miguel Carceller <22276694+jmcarcell@users.noreply.github.com> Date: Thu, 4 Jul 2024 11:24:06 +0200 Subject: [PATCH 40/42] Change an unset variable by a header name (#348) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a5fc00744..22f852392 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,7 +103,7 @@ set(FILES_DEPENDINGON_DCH_INFO_H "DriftChamber_o1_v02.cpp" ) if(NOT DCH_INFO_H_EXIST) list(FILTER sources EXCLUDE REGEX "${FILES_DEPENDINGON_DCH_INFO_H}") - message(WARNING "Subdetector ${FILES_DEPENDINGON_DCH_INFO_H} will not be built because header file ${DCH_INFO_H} was not found") + message(WARNING "Subdetector ${FILES_DEPENDINGON_DCH_INFO_H} will not be built because header file DDRec/DCH_info.h was not found") endif() file(GLOB G4sources From 199839705a6397153a302db270f3484aa700b390 Mon Sep 17 00:00:00 2001 From: jmcarcell Date: Mon, 8 Jul 2024 13:00:07 +0200 Subject: [PATCH 41/42] Add concurrency to the Key4hep workflows --- .github/workflows/downstream-build.yaml | 7 +++++++ .github/workflows/key4hep-build.yaml | 3 +++ 2 files changed, 10 insertions(+) diff --git a/.github/workflows/downstream-build.yaml b/.github/workflows/downstream-build.yaml index df5bac57d..f46a66469 100644 --- a/.github/workflows/downstream-build.yaml +++ b/.github/workflows/downstream-build.yaml @@ -1,9 +1,16 @@ +# Do not edit this file, it will be overwritten! +# The template file can be found in +# https://github.com/key4hep/key4hep-actions/blob/main/workflows/downstream-build.yaml name: downstream-build on: pull_request: workflow_dispatch: +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: downstream-build: runs-on: ubuntu-latest diff --git a/.github/workflows/key4hep-build.yaml b/.github/workflows/key4hep-build.yaml index f0bcb2c11..6a0ea2839 100644 --- a/.github/workflows/key4hep-build.yaml +++ b/.github/workflows/key4hep-build.yaml @@ -12,6 +12,9 @@ on: schedule: - cron: '16 5 * * *' +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: build: From 2e1bba216879562382ea5599b738c14c0938b540 Mon Sep 17 00:00:00 2001 From: Mahmoud Ali Date: Mon, 8 Jul 2024 18:16:19 +0200 Subject: [PATCH 42/42] [IDEA] Adding the detailed version of the muon system. (#322) * Adding the builders of the muon system, including the first draft of the detailed version(barrel and endcap in the same builder) * The first draft of xml file for the detailed version of the muon system * Describing the material of the microRWELL * Adding the parameters(dimensions) of the muon system * Including the muon system into the full IDEA XML * IDEA muon system description, with code details * Including muonSystem directory into Sources * Modifying the muon system factory to avoid overlapping between the different volumes * rename muon system v01 compact file * Adding a new compact file for muon system * Definning muon system IDs and parameters * Adding muon xml to IDEA detector geometry master file * [IDEA_o1_v03]Adding muon system to new version of IDEA * Updating IDEA Readme file with the new additions of muon system * Renamming the compact file of IDEA the muon system and it's readout for homogeneity with the other detectors * Updating the names of the new muon system compact file and commenting si-wrapper * Updating Readme and explainning the builder more in the comments * Re-adding the description of IDEA magentic field * [IDEA Muon System] Clarifying the dimensions description with more comments * Renaming MuRwell materials with removing hex codes in names * Removing Indentation and re-organizing the muon system builder * Simplifying the calculation of detector side envelope * Refactoring Muon-System builder, and making the compact file simpler and more automated * Refactoring Muon-system bit-field * Solving overlap between muon-system barrel and endcap * Removing Muon system from IDEA_v02 * Commenting muon-system builder and compact file for more details * Readding all sub-detectors to IDEA_v03 * Update muonSystem/README.md Co-authored-by: Brieuc Francois * Update FCCee/IDEA/compact/README.md Co-authored-by: Brieuc Francois * Fixing typo in IDEA muon-systm cmpact file * Fixing typo in IDEA muon-systm compact file --------- Co-authored-by: Brieuc Francois --- CMakeLists.txt | 1 + .../DectDimensions_IDEA_o1_v03.xml | 27 + .../IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml | 3 + .../compact/IDEA_o1_v03/MuonSystem_o1_v01.xml | 69 ++ .../compact/IDEA_o1_v03/materials_o1_v02.xml | 203 ++++ FCCee/IDEA/compact/README.md | 4 +- detector/muonSystem/README.md | 10 + .../muonSystem/muonSystemMuRWELL_o1_v01.cpp | 946 ++++++++++++++++++ 8 files changed, 1261 insertions(+), 2 deletions(-) create mode 100644 FCCee/IDEA/compact/IDEA_o1_v03/MuonSystem_o1_v01.xml create mode 100644 detector/muonSystem/README.md create mode 100644 detector/muonSystem/muonSystemMuRWELL_o1_v01.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 22f852392..307bef2a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,7 @@ file(GLOB sources ./detector/tracker/*.cpp ./detector/calorimeter/*.cpp ./detector/fcal/*.cpp + ./detector/muonSystem/*.cpp ./detector/other/*.cpp ./detector/CaloTB/*.cpp ./FCalTB/setup/*.cpp diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v03.xml b/FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v03.xml index f3779cf19..cf080fa0c 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v03.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v03/DectDimensions_IDEA_o1_v03.xml @@ -53,6 +53,8 @@ + + @@ -214,6 +216,21 @@ + + + + + + + + + + + + + + + @@ -262,6 +279,16 @@ + + + + + + + + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml b/FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml index ff2bbf3db..5ebedf0ed 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v03/IDEA_o1_v03.xml @@ -53,6 +53,9 @@ + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/MuonSystem_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v03/MuonSystem_o1_v01.xml new file mode 100644 index 000000000..5369f185b --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v03/MuonSystem_o1_v01.xml @@ -0,0 +1,69 @@ + + + + + It depends on the factory: muonSystemMuRWELL_o1_v01 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system:5,type:2,layer:4,chamber:15,slice:1,y:-10,z:-10 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v03/materials_o1_v02.xml b/FCCee/IDEA/compact/IDEA_o1_v03/materials_o1_v02.xml index cdf85f605..aea439da0 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v03/materials_o1_v02.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v03/materials_o1_v02.xml @@ -395,4 +395,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/IDEA/compact/README.md b/FCCee/IDEA/compact/README.md index fc2eb6045..4239c24d4 100644 --- a/FCCee/IDEA/compact/README.md +++ b/FCCee/IDEA/compact/README.md @@ -9,10 +9,10 @@ IDEA version picked from the latest version in FCCDetectors repo IDEA_o1_v02 ------------ -Based on o1_v01 but with a detailed description of the vertex detector and the drift chamber, a place holder solenoid and the endplate absorber. Missing: SiWrapper, calorimeter, detailed muons system (coming soon). +Based on o1_v01 but with a detailed description of the vertex detector, drift chamber, a place holder solenoid and the endplate absorber. Missing: SiWrapper, calorimeter. IDEA_o1_v03 ------------ -Based on o1_v02 but replacing the drift chamber (o1, v01) for the lightweight implementation based on twisted tubes (o1, v02). Production threshold and step limit physics have to be tuned +Based on o1_v02 but replacing the drift chamber (o1, v01) for the lightweight implementation based on twisted tubes (o1, v02). NB: production threshold and step limit physics have to be tuned for the drift chamber. July 2024: Added a detailed version of the muon system. diff --git a/detector/muonSystem/README.md b/detector/muonSystem/README.md new file mode 100644 index 000000000..31d317cf6 --- /dev/null +++ b/detector/muonSystem/README.md @@ -0,0 +1,10 @@ +# µRWELL Based Muon System + +The IDEA detector concept includes a muon detection system and pre-shower designed using µRWELL technology. Each station consists of a large mosaic of 50 × 50 cm² µRWELL detectors. For more technical details about the new detector technology, see the [µRWELL](https://iopscience.iop.org/article/10.1088/1748-0221/10/02/P02008). + +## muonSystemMuRWELL_o1_v01.cpp +The first version of the detailed muon system driver, it can be used to describe both barrel and endcap, if you want to eleminate one of them, just set the number of layers= 0. +The code has been designed to be very flexible, where the user can choose the number of sides in the R-Phi plane, `numSides` (hexagon, octagon, etc), and the detector builder will automatically calculate the number and places of the copied chambers. Some of the code advantages: + * If the side length do not fit with an integer number of 50 × 50 cm² , the builder will make a chamber with unusual dimensions, which can fit the excess area at the end of the side. + * The availability to make multiple layers with different inner radius and barrel length. + * The code is very general, it can be used to describe any detector system made from repeated tiles (e.g. pre-shower) and has the capability to fill the gaps with unusual dimensions tiles. diff --git a/detector/muonSystem/muonSystemMuRWELL_o1_v01.cpp b/detector/muonSystem/muonSystemMuRWELL_o1_v01.cpp new file mode 100644 index 000000000..539f6f8e6 --- /dev/null +++ b/detector/muonSystem/muonSystemMuRWELL_o1_v01.cpp @@ -0,0 +1,946 @@ +/* + @author: Mahmoud Ali +mahmoud.ali@cern.ch + +Factory for IDEA muon system +Expected xml structure (the 'sensitive' keyword is optional and defaults to false): + + + + + + + + + + + . . . . + + + +If used with sensitive layers, the readout must contain a "slice" field +*/ + + +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/Printout.h" +#include "XML/XMLElements.h" +#include +#include +#include + +using namespace std; +using namespace dd4hep; + +static dd4hep::Ref_t createmuonSystemMuRWELL_o1_v01(dd4hep::Detector& lcdd, + dd4hep::xml::Handle_t xmlElement, + dd4hep::SensitiveDetector sensDet) { + dd4hep::xml::DetElement xmlDet = static_cast(xmlElement); + std::string name = xmlDet.nameStr(); + dd4hep::DetElement detElement(name, xmlDet.id()); + dd4hep::Material mat = lcdd.material("Air"); + dd4hep::Volume experimentalHall = lcdd.pickMotherVolume(detElement); + + xml_comp_t dimensions(xmlDet.dimensions()); + + // ---------------------------------------------------------------------------------------------------- + // --- General parameters --- + + auto generalParameters = xmlElement.child(_Unicode(generalParameters)); + int numSides = generalParameters.attr("numSides"); + double overlapY = generalParameters.attr("overlapY"); + double overlapZ = generalParameters.attr("overlapZ"); + double clearance = generalParameters.attr("clearance"); // it's a small distance to be used to avoid overlapping between the different volumes ~ 1 mm + + // --- Barrel parameters --- + + auto Barrel = xmlElement.child(_Unicode(Barrel)); + int numBarrelDetectorLayers = Barrel.attr("numDetectorLayers"); + double radius = Barrel.attr("rmin"); + double barrelLength = Barrel.attr("length"); + int numBarrelRadiators = Barrel.attr("numYokes"); + double barrelRadiatorThickness = Barrel.attr("yoke_Thickness"); + dd4hep::Material barrelRadiatorMaterial = lcdd.material(Barrel.attr("yoke_Material")); + + // --- Endcap parameters --- + + auto Endcap = xmlElement.child(_Unicode(Endcap)); + int numEndcapDetectorLayers = Endcap.attr("numDetectorLayers"); + double endcapDetectorLayerInnerRadius = Endcap.attr("rmin"); + double endcapDetectorLayerOuterRadius = Endcap.attr("rmax"); + double endcapZOffset = Endcap.attr("z_offset"); + int numEndcapRadiators = Endcap.attr("numYokes"); + double endcapRadiatorThickness = Endcap.attr("yoke_Thickness"); + double endcapRadiatorLayerInnerRadius = endcapDetectorLayerInnerRadius; + double endcapRadiatorLayerOuterRadius = endcapDetectorLayerOuterRadius; + dd4hep::Material endcapRadiatorMaterial = lcdd.material(Endcap.attr("yoke_Material")); + + // ----------------------------------------------------------------------------------------------------------- + + double shapeAngle = 360.0 / numSides; // it's the full angle + double shapeAngle_radians = M_PI / numSides; // Isn't it a half angle!! + double angle_clearance = 0.0; // 0.02 works good but needs the detector volume thick to be more than 60 mm. // it's less than 1 degree, we use the clearnce to avoid overlapping + + double chamberAngle_rad = std::atan(dimensions.x()/dimensions.y()); + double rectangleThickness = (2 * dimensions.y()) * std::sin(chamberAngle_rad) + (2 * dimensions.x()) * std::cos(chamberAngle_rad) + 1.2 * clearance; + double rectangleAngle_rad = std::atan(rectangleThickness/dimensions.z()); + double detectorVolumeThickness = (2 * dimensions.z()) * std::sin(rectangleAngle_rad) + rectangleThickness * std::cos(rectangleAngle_rad); + + double endcapDetectorSideLength = (2 * (endcapDetectorLayerInnerRadius) * std::tan(shapeAngle_radians)) + 42.0; // shouldn't be hardcoded, but // the offset of 42.0 cm to avoid the overalp with the rectangles + + double endcapDetectorSideTrapLength = (2 * (endcapDetectorLayerOuterRadius - 2 * dimensions.z()) * std::tan(shapeAngle_radians)) + 42.0; // the offset of 42.0 cm to avoid the overalp with the rectangles + double endcapDetectorSideTrapYLength = endcapDetectorLayerOuterRadius - 2 * dimensions.z() - endcapDetectorLayerInnerRadius; + double endcapDetectorSideBoxLength = 2 * (endcapDetectorLayerOuterRadius) * std::tan(shapeAngle_radians); + double endcapDetectorSideBoxYLength = 2 * dimensions.z(); + + // endcapRadiatorSideLength and endcapRadiatorSideLength2 are the lengths of the parallel sides of the trapezoid. + double endcapRadiatorSideLength = 2 * (endcapRadiatorLayerInnerRadius) * std::tan(shapeAngle_radians); //it is also the same for the endcap detector layers. + double endcapRadiatorSideLength2 = 2 * (endcapRadiatorLayerOuterRadius) * std::tan(shapeAngle_radians); //it is also the same for the endcap detector layers. + + double endcapDetectorYLength = endcapDetectorLayerOuterRadius - endcapDetectorLayerInnerRadius; + double endcapYLength = endcapRadiatorLayerOuterRadius - endcapRadiatorLayerInnerRadius; // It is the distance betwwen the inner and the outer radius of the endcap, it can be in both Y and X dimensions //it is also the same for the endcap detector layers. + + double endcapRemainderZ = std::fmod((endcapDetectorYLength - 2 * clearance), (2 * dimensions.z() - overlapZ)) / (2 * dimensions.z()) - (2 * clearance / dimensions.z()); + + double endcapDetectorEnvZ = detectorVolumeThickness; // layer thickness + + double barrelRMax = radius + numBarrelDetectorLayers * (2 * detectorVolumeThickness) + numBarrelRadiators * barrelRadiatorThickness; + double barreltotalLength = barrelLength + (numEndcapDetectorLayers * 2) * (2 * detectorVolumeThickness) + (numEndcapRadiators * 2) * endcapRadiatorThickness; // This condition to make the last barrel layer encloses all the endcap layers inside it. + double EndcaptotalLength = numEndcapDetectorLayers * (2 * detectorVolumeThickness) + numEndcapRadiators * endcapRadiatorThickness; + double endcapOffset = endcapZOffset + EndcaptotalLength/2.0; + + int barrelIdCounter = 1; + int endcapIdCounter = 1; + + //-------------------------// Building system envelope //---------------------------- + + dd4hep::PolyhedraRegular BarrelEnv(numSides, radius, barrelRMax, barreltotalLength); + dd4hep::PolyhedraRegular EndcapEnv(numSides, endcapDetectorLayerInnerRadius, endcapDetectorLayerOuterRadius, EndcaptotalLength); + + double unionOffsetZpositive = endcapOffset; + double unionOffsetZnegative = -endcapOffset; + + dd4hep::Position unionPos(0.0 , 0.0, unionOffsetZpositive); + dd4hep::Position unionPos2(0.0 , 0.0, unionOffsetZnegative); + dd4hep::Rotation3D unionRot(dd4hep::RotationY(0.0 * dd4hep::degree)); + + dd4hep::Transform3D unionTransform(unionRot, unionPos); + dd4hep::Transform3D unionTransform2(unionRot, unionPos2); + + //Combining two shapes by UnionSolid: the first shape is centralized and the second transform around the first.. + dd4hep::UnionSolid barrelAndPositiveEndcap(BarrelEnv, EndcapEnv, unionTransform); + dd4hep::UnionSolid systemEnvelope(barrelAndPositiveEndcap, EndcapEnv, unionTransform2); + dd4hep::Volume detectorVolume(name, systemEnvelope, mat); + +// ---------------------------------------------------------------------------------------------------- +// ------------------------------// B A R R E L // ---------------------------------------------------- + + dd4hep::PolyhedraRegular BarrelEnvWithoutLastLayer(numSides, radius, barrelRMax, barrelLength); + dd4hep::PolyhedraRegular BarrelLastLayerEnv(numSides, (barrelRMax - 2 * detectorVolumeThickness), barrelRMax, barreltotalLength); + std::string barrelName = dd4hep::xml::_toString(0, "MS-Barrel%d"); + + dd4hep::Position barrelUnionPos(0.0 , 0.0, 0.0); + dd4hep::Rotation3D barrelUnionRot(dd4hep::RotationY(0.0 * dd4hep::degree)); + dd4hep::Transform3D barrelUnionTransform(barrelUnionRot, barrelUnionPos); + + dd4hep::UnionSolid barrelUnion(BarrelEnvWithoutLastLayer, BarrelLastLayerEnv, barrelUnionTransform); + dd4hep::Volume BarrelVolume(barrelName, barrelUnion, mat); + + dd4hep::Position barrelTrans(0., 0., 0.); + dd4hep::PlacedVolume barrelPhys = detectorVolume.placeVolume(BarrelVolume, dd4hep::Transform3D(dd4hep::RotationZ(0.), barrelTrans)); + barrelPhys.addPhysVolID("type", 0); + dd4hep::DetElement BarrelDE(detElement, "MSBarrelDE" , 0); + BarrelDE.setPlacement(barrelPhys); + BarrelVolume.setVisAttributes(lcdd.visAttributes("no_vis")); + + // ---------- loop to creat the barrel layers ----------- + + for (int numBarrelLayer = 0; numBarrelLayer < numBarrelDetectorLayers; ++numBarrelLayer){ + + double barrelLayerRMin = radius + numBarrelLayer * (2 * detectorVolumeThickness) + numBarrelLayer * barrelRadiatorThickness; // Automation of inner radius of different layers, taking into account that every detector layer is followed by a yoke(radiator) layer. + double barrelLayerRMax = barrelLayerRMin + 2 * detectorVolumeThickness; + double barrelLayerRMid = (barrelLayerRMin + barrelLayerRMax)/ 2.0; + double barrelLayerLength; + if (numBarrelLayer == numBarrelDetectorLayers - 1){ + barrelLayerLength = barrelLength + (numEndcapDetectorLayers * 2) * (2 * detectorVolumeThickness) + (numEndcapRadiators * 2) * endcapRadiatorThickness; // This condition to make the last barrel layer encloses all the endcap layers inside it. + } else { + barrelLayerLength = barrelLength; + } + + dd4hep::PolyhedraRegular BarrelDetectorLayer(numSides, barrelLayerRMin, barrelLayerRMax, barrelLayerLength); + std::string barrelDetectorName = dd4hep::xml::_toString(numBarrelLayer +1, "MS-BarrelDetectorLayer%d"); + dd4hep::Volume BarrelDetectorLayerVolume(barrelDetectorName, BarrelDetectorLayer, mat); + + // sideLength and sideLength2 are the lengths of the parallel sides of the trapezoid. + double sideLength = 2 * (barrelLayerRMid - detectorVolumeThickness/2.0) * std::tan(shapeAngle_radians); + double sideLength2 = 2 * (barrelLayerRMid + detectorVolumeThickness/2.0) * std::tan(shapeAngle_radians); + double sideEnvX = detectorVolumeThickness/2.0; + double sideEnvY = (sideLength / 2.0); + double sideEnvY2 = (sideLength2 / 2.0); + double sideEnvZ = (barrelLayerLength / 2.0); + double remainderZ = std::fmod((barrelLayerLength - 2 * clearance), (2 * dimensions.z() - overlapZ)) / (2 * dimensions.z()) - (2 * clearance / dimensions.z()); + + for (int side = 0; side < numSides; ++side) { + + int sideID = (numBarrelLayer + 1) * 100 + (side +1); // to differentiated with the same side in different layers. + dd4hep::Box sideEnvelope(sideEnvX, sideEnvY, sideEnvZ); + dd4hep::Box sideEnvelope2(sideEnvX, sideEnvY2, sideEnvZ); + std::string sideName = dd4hep::xml::_toString(sideID, "side%d"); + dd4hep::Volume sideVol(sideName, sideEnvelope, mat); + dd4hep::Volume sideVol2(sideName, sideEnvelope2, mat); + + double angle_degrees = shapeAngle * side; // Calculate the angle for each side + double angle_radians = angle_degrees * M_PI / 180.0; + + double sideXOffset = (barrelLayerRMid - detectorVolumeThickness/2.0) * std::cos(angle_radians+shapeAngle_radians); + double sideYOffset = (barrelLayerRMid - detectorVolumeThickness/2.0) * std::sin(angle_radians+shapeAngle_radians); + + double sideXOffset2 = (barrelLayerRMid + detectorVolumeThickness/2.0) * std::cos(angle_radians+shapeAngle_radians); + double sideYOffset2 = (barrelLayerRMid + detectorVolumeThickness/2.0) * std::sin(angle_radians+shapeAngle_radians); + + dd4hep::RotationZ sideRotationZ(angle_radians+shapeAngle_radians+angle_clearance); + dd4hep::Rotation3D sideRotation = dd4hep::Rotation3D(sideRotationZ); + + double sideXPos = sideXOffset ; + double sideYPos = sideYOffset ; + double sideZPos = 0.0; + double sideXPos2 = sideXOffset2 ; + double sideYPos2 = sideYOffset2 ; + + dd4hep::Position sideTrans; + dd4hep::PlacedVolume sidePhys; + dd4hep::DetElement sideDE; + + if (side % 2 == 0) { + sideTrans = dd4hep::Position(sideXPos, sideYPos, sideZPos); + sidePhys = BarrelDetectorLayerVolume.placeVolume(sideVol, dd4hep::Transform3D(sideRotation, sideTrans)); + } else { + sideTrans = dd4hep::Position(sideXPos2, sideYPos2, sideZPos); + sidePhys = BarrelDetectorLayerVolume.placeVolume(sideVol2, dd4hep::Transform3D(sideRotation, sideTrans)); + } + + sideDE = dd4hep::DetElement(detElement, sideName + "DE", sideID); + sideDE.setPlacement(sidePhys); + sideVol.setVisAttributes(lcdd, xmlDet.visStr()); + sideVol2.setVisAttributes(lcdd, xmlDet.visStr()); + + // ------------------------------------------------------------------------------------------------------- + // Dividing every side to small rectangles // + // ------------------------------------------------------------------------------------------------------- + + int numRectangles = barrelLayerLength / (2 * dimensions.z() - overlapZ); // numbers of the rectangles in each side.. depends on the number of the chambers that can be overlapped in Z direction + + for (int rectangle = 0; rectangle < (numRectangles + 1); ++rectangle) { + + double rectangleEnvX = detectorVolumeThickness/4.5; // dividing by 4.5 gets the best thickness for the recatngle to avoid any overlap ~ in our case the uRWELL the best rectangle thickness is 26.667 mm which is 120/4.5. + double rectangleEnvY; + if (side % 2 == 0) { + rectangleEnvY = sideLength / 2.0; // + clearance; + } else { + rectangleEnvY = sideLength2 / 2.0; // + clearance; + } + double rectangleEnvZ = dimensions.z() + clearance/2.0; + double rectangleRemainderEnvZ = (remainderZ * dimensions.z()) + clearance/4.0; // this is the last rectangle in the side, and it is smaller than the usual one, with larger rotation angle. so it need to be shorter in length to avoid overlap. + + dd4hep::Box rectangleEnvelope(rectangleEnvX, rectangleEnvY, rectangleEnvZ); + std::string rectangleEnvelopeName = dd4hep::xml::_toString(rectangle, "rectangleEnvelope%d"); + dd4hep::Volume rectangleEnvVol(rectangleEnvelopeName, rectangleEnvelope, mat); + + dd4hep::Box rectangleRemainderEnvelope(rectangleEnvX, rectangleEnvY, rectangleRemainderEnvZ); + std::string rectangleRemainderEnvelopeName = dd4hep::xml::_toString(rectangle, "rectangleRemainderEnvelope%d"); + dd4hep::Volume rectangleRemainderEnvVol(rectangleRemainderEnvelopeName, rectangleRemainderEnvelope, mat); + + double rectangleEnvXPos = 0.0; + double rectangleEnvYPos = 0.0; + double rectangleEnvZPos = barrelLayerLength/2.0 - dimensions.z() - (rectangle * (2 * dimensions.z() - overlapZ)) - clearance; + double rectangleRemainderEnvXPos = sideEnvX/2.0; + double rectangleRemainderEnvZPos = barrelLayerLength/2.0 - (remainderZ * dimensions.z()) - (rectangle * (2 * dimensions.z() - overlapZ)) - clearance; + + double yRotation = std::atan(rectangleEnvX / (rectangleEnvZ - (2 * overlapZ))); + double yRemainderRotation = std::atan(rectangleEnvX / (rectangleRemainderEnvZ - (2 * overlapZ))); + dd4hep::RotationY rotationY(yRotation); + dd4hep::RotationY remainderRotationY; + if (rectangleRemainderEnvZ <= rectangleEnvZ/10.0) { + remainderRotationY = dd4hep::RotationY(yRotation); + } else { + remainderRotationY = dd4hep::RotationY(yRemainderRotation); + } + + // _________________________________________________________________________________________________ + if (rectangle == numRectangles) { + + dd4hep::Position rectangeEnvelopeTrans; + if (rectangleRemainderEnvZ <= rectangleEnvZ/10.0) { + rectangeEnvelopeTrans = dd4hep::Position(rectangleRemainderEnvXPos, rectangleEnvYPos, rectangleRemainderEnvZPos); + } else { + rectangeEnvelopeTrans = dd4hep::Position(rectangleEnvXPos, rectangleEnvYPos, rectangleRemainderEnvZPos); + } + dd4hep::PlacedVolume rectangleEnvelopePhys; + if (side % 2 == 0) { + rectangleEnvelopePhys = sideVol.placeVolume(rectangleRemainderEnvVol, dd4hep::Transform3D(remainderRotationY, rectangeEnvelopeTrans)); + } else { + rectangleEnvelopePhys = sideVol2.placeVolume(rectangleRemainderEnvVol, dd4hep::Transform3D(remainderRotationY, rectangeEnvelopeTrans)); + } + dd4hep::DetElement rectangleEnvelopeDE(sideDE, rectangleRemainderEnvelopeName + "DE", rectangle); + rectangleEnvelopeDE.setPlacement(rectangleEnvelopePhys); + rectangleEnvVol.setVisAttributes(lcdd, xmlDet.visStr()); + + // ------------------------ start to build the chamber envelopes ------------------- + + int numChambersInRectangle = 2 * rectangleEnvY / (2 * dimensions.y() - overlapY); // number of the chambers in each rectangle + + for (int chamberIndex = 0; chamberIndex < (numChambersInRectangle + 1); chamberIndex++) { + + std::stringstream barrelNameStream; + barrelNameStream << "MuRWELL_Barrel_" << barrelIdCounter++; + std::string BarrelChamberName = barrelNameStream.str(); + + dd4hep::Box envelope(dimensions.x(), dimensions.y(), remainderZ * dimensions.z()); + dd4hep::Volume envVolume(BarrelChamberName, envelope, lcdd.material(dimensions.materialStr())); + + double rectangleRemainderY = std::fmod(2 * (rectangleEnvY - clearance), (2 * dimensions.y() - overlapY)) / (2 * dimensions.y()); + + dd4hep::Box rectangleRemainderYEnvelope(dimensions.x(), rectangleRemainderY * dimensions.y(), remainderZ * dimensions.z()); + dd4hep::Volume rectangleRemainderYEnvVolume(BarrelChamberName + "rectangleRemainderY", rectangleRemainderYEnvelope, lcdd.material(dimensions.materialStr())); + + double envYPos = (chamberIndex * 2 * dimensions.y()) - (overlapY * chamberIndex) + dimensions.y_offset() - rectangleEnvY + dimensions.y() + clearance/20.0 ; // found that the positioning of the chambers inside the rectangle had an overlap with the mother volume ~ 45 um. + double rectangleRemainderREnvYPos = (chamberIndex * 2 * dimensions.y()) - (overlapY * chamberIndex) + dimensions.y_offset() - rectangleEnvY + rectangleRemainderY * dimensions.y() + clearance/20.0; + + double zRotation = std::atan(dimensions.x() / (dimensions.y() - (2 * overlapY))); + dd4hep::RotationZ chamberRotation(zRotation); + + double rectangleRemainderZRotation = std::atan(dimensions.x() / (rectangleRemainderY * dimensions.y() - (2 * overlapY))); // Y and Z are reversed in local remainder + dd4hep::RotationZ rectangleRemainderRotationZ(rectangleRemainderZRotation); + + auto Slices = xmlElement.children(_Unicode(slice)); + auto numSlices = xmlElement.numChildren(_Unicode(slice), true); + dd4hep::xml::Handle_t slice(Slices.reset()); + int sensitiveSliceIndex = 0; + + // --- two cases : one for remainder chambers ---------------------------------------------- + + if (chamberIndex == numChambersInRectangle) { + + dd4hep::Position rectangleRemainderTrans(dimensions.x_offset(), rectangleRemainderREnvYPos, 0.0); + dd4hep::PlacedVolume rectangleRemainderEnvPhys = rectangleRemainderEnvVol.placeVolume(rectangleRemainderYEnvVolume, dd4hep::Transform3D(rectangleRemainderRotationZ, rectangleRemainderTrans)); + rectangleRemainderEnvPhys.addPhysVolID("chamber", barrelIdCounter); + dd4hep::DetElement rectangleRemainderEnvDE(rectangleEnvelopeDE, BarrelChamberName, barrelIdCounter); + rectangleRemainderEnvDE.setPlacement(rectangleRemainderEnvPhys); + rectangleRemainderYEnvVolume.setVisAttributes(lcdd, xmlDet.visStr()); + // std::cout << "Adding detector element: " << detElement.name() << " to path: " << detElement.path() << std::endl; + + double sliceXOffset = - dimensions.x(); + for (unsigned sliceIdx = 0; sliceIdx < numSlices; ++sliceIdx) { + dd4hep::xml::DetElement sliceDet = static_cast(slice); + dd4hep::Box sliceShape(sliceDet.x(), rectangleRemainderY * dimensions.y(), remainderZ * dimensions.z()); // I made the y-z dimensions of the slices are the same like the chamber (which is normal case in most of the detectors), if you need change any slice y-z dimension replace dimensions.y() with sliceDet.y() + std::string sliceName = dd4hep::xml::_toString(sliceIdx, "slice%d"); + dd4hep::Volume sliceVolume(sliceName, sliceShape, lcdd.material(slice.attr("material"))); + + dd4hep::Position transSlice(sliceXOffset + sliceDet.x(), 0.0, 0.0); // all the slices are centered in the chamber except in x-axis they are accumalted over each other respectivley.. If you want to add an offset to any direction by the user you can add sliceDet.y_offset() instead of 0. + dd4hep::PlacedVolume slicePlacedVolume = rectangleRemainderYEnvVolume.placeVolume(sliceVolume, dd4hep::Transform3D(dd4hep::RotationZ(0.), transSlice)); + + if (slice.hasAttr("vis")) { + sliceVolume.setVisAttributes(lcdd, sliceDet.visStr()); + } + if (slice.hasAttr("sensitive") && sliceDet.isSensitive()) { + dd4hep::xml::Dimension sdType(xmlElement.child(_U(sensitive))); + sensDet.setType(sdType.typeStr()); + sliceVolume.setSensitiveDetector(sensDet); + slicePlacedVolume.addPhysVolID("slice", sensitiveSliceIndex); + // dd4hep::printout(dd4hep::INFO,"Sensitive Slice has been created at", name, BarrelChamberName); + sensitiveSliceIndex++; + } + // Increment the current x-offset by the width of the current slice + sliceXOffset += (2 * sliceDet.x()); + slice.m_node = Slices.next(); + } + + // ---------------- Second case: for the full chambers + } else { + + dd4hep::Position trans(dimensions.x_offset(), envYPos, 0.0); + dd4hep::PlacedVolume envPhys = rectangleRemainderEnvVol.placeVolume(envVolume, dd4hep::Transform3D(chamberRotation, trans)); + envPhys.addPhysVolID("chamber", barrelIdCounter); + dd4hep::DetElement envDE(rectangleEnvelopeDE, BarrelChamberName, barrelIdCounter); + envDE.setPlacement(envPhys); + envVolume.setVisAttributes(lcdd, xmlDet.visStr()); + + // std::cout << "Adding detector element: " << detElement.name() << " to path: " << detElement.path() << std::endl; + double sliceXOffset = - dimensions.x(); + for (unsigned sliceIdx = 0; sliceIdx < numSlices; ++sliceIdx) { + dd4hep::xml::DetElement sliceDet = static_cast(slice); + dd4hep::Box sliceShape(sliceDet.x(), dimensions.y(), remainderZ * dimensions.z()); + std::string sliceName = dd4hep::xml::_toString(sliceIdx, "slice%d"); + dd4hep::Volume sliceVolume(sliceName, sliceShape, lcdd.material(slice.attr("material"))); + dd4hep::Position transSlice(sliceXOffset + sliceDet.x(), 0.0, 0.0); + dd4hep::PlacedVolume slicePlacedVolume = envVolume.placeVolume(sliceVolume, dd4hep::Transform3D(dd4hep::RotationZ(0.), transSlice)); + + + if (slice.hasAttr("vis")) { + sliceVolume.setVisAttributes(lcdd, sliceDet.visStr()); + } + if (slice.hasAttr("sensitive") && sliceDet.isSensitive()) { + dd4hep::xml::Dimension sdType(xmlElement.child(_U(sensitive))); + sensDet.setType(sdType.typeStr()); + sliceVolume.setSensitiveDetector(sensDet); + slicePlacedVolume.addPhysVolID("slice", sensitiveSliceIndex); + // dd4hep::printout(dd4hep::INFO,"Sensitive slice has been created at", name, BarrelChamberName); + sensitiveSliceIndex++; + } + // Increment the current x-offset by the width of the current slice + sliceXOffset += (2 * sliceDet.x()); + slice.m_node = Slices.next(); + } + } + } + + } else { + // ......_____________________________________________________________________________________________ + + dd4hep::Position rectangeEnvelopeTrans(rectangleEnvXPos, rectangleEnvYPos, rectangleEnvZPos); + dd4hep::PlacedVolume rectangleEnvelopePhys; + if (side % 2 == 0) { + rectangleEnvelopePhys = sideVol.placeVolume(rectangleEnvVol, dd4hep::Transform3D(rotationY, rectangeEnvelopeTrans)); + } else { + rectangleEnvelopePhys = sideVol2.placeVolume(rectangleEnvVol, dd4hep::Transform3D(rotationY, rectangeEnvelopeTrans)); + } + dd4hep::DetElement rectangleEnvelopeDE(sideDE, rectangleEnvelopeName + "DE", rectangle); + rectangleEnvelopeDE.setPlacement(rectangleEnvelopePhys); + rectangleEnvVol.setVisAttributes(lcdd, xmlDet.visStr()); + + + // ------------------------ start to build the chamber envelopes ------------------- + + int numChambersInRectangle = 2 * rectangleEnvY / (2 * dimensions.y() - overlapY); // number of the chambers in each rectangle + + for (int chamberIndex = 0; chamberIndex < (numChambersInRectangle + 1); chamberIndex++) { + + std::stringstream barrelNameStream; + barrelNameStream << "MuRWELL_Barrel_" << barrelIdCounter++; + std::string BarrelChamberName = barrelNameStream.str(); + + dd4hep::Box envelope(dimensions.x(), dimensions.y(), dimensions.z()); + dd4hep::Volume envVolume(BarrelChamberName, envelope, lcdd.material(dimensions.materialStr())); + + double rectangleRemainderY = std::fmod(2 * (rectangleEnvY - clearance), (2 * dimensions.y() - overlapY)) / (2 * dimensions.y()); + + dd4hep::Box rectangleRemainderYEnvelope(dimensions.x(), rectangleRemainderY * dimensions.y(), dimensions.z()); + dd4hep::Volume rectangleRemainderYEnvVolume(BarrelChamberName + "rectangleRemainderY", rectangleRemainderYEnvelope, lcdd.material(dimensions.materialStr())); + + double envYPos = (chamberIndex * 2 * dimensions.y()) - (overlapY * chamberIndex) + dimensions.y_offset() - rectangleEnvY + dimensions.y() + clearance/20.0 ; // found that the positioning of the chambers inside the rectangle had an overlap with the mother volume ~ 45 um. + double rectangleRemainderREnvYPos = (chamberIndex * 2 * dimensions.y()) - (overlapY * chamberIndex) + dimensions.y_offset() - rectangleEnvY + rectangleRemainderY * dimensions.y() + clearance/20.0; + + double zRotation = std::atan(dimensions.x() / (dimensions.y() - (2 * overlapY))); + dd4hep::RotationZ chamberRotation(zRotation); + + double rectangleRemainderZRotation = std::atan(dimensions.x() / (rectangleRemainderY * dimensions.y() - (2 * overlapY))); // Y and Z are reversed in local remainder + dd4hep::RotationZ rectangleRemainderRotationZ(rectangleRemainderZRotation); + + auto Slices = xmlElement.children(_Unicode(slice)); + auto numSlices = xmlElement.numChildren(_Unicode(slice), true); + dd4hep::xml::Handle_t slice(Slices.reset()); + int sensitiveSliceIndex = 0; + + // --- two cases : one for remainder chambers ---------------------------------------------- + + if (chamberIndex == numChambersInRectangle) { + + dd4hep::Position rectangleRemainderTrans(dimensions.x_offset(), rectangleRemainderREnvYPos, 0.0); + dd4hep::PlacedVolume rectangleRemainderEnvPhys = rectangleEnvVol.placeVolume(rectangleRemainderYEnvVolume, dd4hep::Transform3D(rectangleRemainderRotationZ, rectangleRemainderTrans)); + rectangleRemainderEnvPhys.addPhysVolID("chamber", barrelIdCounter); + dd4hep::DetElement rectangleRemainderEnvDE(rectangleEnvelopeDE, BarrelChamberName, barrelIdCounter); + rectangleRemainderEnvDE.setPlacement(rectangleRemainderEnvPhys); + rectangleRemainderYEnvVolume.setVisAttributes(lcdd, xmlDet.visStr()); + + // std::cout << "Adding detector element: " << detElement.name() << " to path: " << detElement.path() << std::endl; + double sliceXOffset = - dimensions.x(); + for (unsigned sliceIdx = 0; sliceIdx < numSlices; ++sliceIdx) { + dd4hep::xml::DetElement sliceDet = static_cast(slice); + dd4hep::Box sliceShape(sliceDet.x(), rectangleRemainderY * dimensions.y(), dimensions.z()); + std::string sliceName = dd4hep::xml::_toString(sliceIdx, "slice%d"); + dd4hep::Volume sliceVolume(sliceName, sliceShape, lcdd.material(slice.attr("material"))); + dd4hep::Position transSlice(sliceXOffset + sliceDet.x(), 0.0, 0.0); + dd4hep::PlacedVolume slicePlacedVolume = rectangleRemainderYEnvVolume.placeVolume(sliceVolume, dd4hep::Transform3D(dd4hep::RotationZ(0.), transSlice)); + + if (slice.hasAttr("vis")) { + sliceVolume.setVisAttributes(lcdd, sliceDet.visStr()); + } + if (slice.hasAttr("sensitive") && sliceDet.isSensitive()) { + dd4hep::xml::Dimension sdType(xmlElement.child(_U(sensitive))); + sensDet.setType(sdType.typeStr()); + sliceVolume.setSensitiveDetector(sensDet); + slicePlacedVolume.addPhysVolID("slice", sensitiveSliceIndex); + //dd4hep::printout(dd4hep::INFO,"Sensitive slice has been created at", name, BarrelChamberName); + sensitiveSliceIndex++; + } + // Increment the current x-offset by the width of the current slice + sliceXOffset += (2 * sliceDet.x()); + slice.m_node = Slices.next(); + } + + // ---------------- Second case: for the full chambers + } else { + + dd4hep::Position trans(dimensions.x_offset(), envYPos, 0.0); + dd4hep::PlacedVolume envPhys = rectangleEnvVol.placeVolume(envVolume, dd4hep::Transform3D(chamberRotation, trans)); + envPhys.addPhysVolID("chamber", barrelIdCounter); + dd4hep::DetElement envDE(rectangleEnvelopeDE, BarrelChamberName, barrelIdCounter); + envDE.setPlacement(envPhys); + envVolume.setVisAttributes(lcdd, xmlDet.visStr()); + + // std::cout << "Adding detector element: " << detElement.name() << " to path: " << detElement.path() << std::endl; + double sliceXOffset = - dimensions.x(); + for (unsigned sliceIdx = 0; sliceIdx < numSlices; ++sliceIdx) { + dd4hep::xml::DetElement sliceDet = static_cast(slice); + dd4hep::Box sliceShape(sliceDet.x(), dimensions.y(), dimensions.z()); + std::string sliceName = dd4hep::xml::_toString(sliceIdx, "slice%d"); + dd4hep::Volume sliceVolume(sliceName, sliceShape, lcdd.material(slice.attr("material"))); + dd4hep::Position transSlice(sliceXOffset + sliceDet.x(), 0.0, 0.0); + dd4hep::PlacedVolume slicePlacedVolume = envVolume.placeVolume(sliceVolume, dd4hep::Transform3D(dd4hep::RotationZ(0.), transSlice)); + + + if (slice.hasAttr("vis")) { + sliceVolume.setVisAttributes(lcdd, sliceDet.visStr()); + } + if (slice.hasAttr("sensitive") && sliceDet.isSensitive()) { + dd4hep::xml::Dimension sdType(xmlElement.child(_U(sensitive))); + sensDet.setType(sdType.typeStr()); + sliceVolume.setSensitiveDetector(sensDet); + slicePlacedVolume.addPhysVolID("slice", sensitiveSliceIndex); + // dd4hep::printout(dd4hep::INFO,"Sensitive slice has been created at", name, BarrelChamberName); + sensitiveSliceIndex++; + } + // Increment the current x-offset by the width of the current slice + sliceXOffset += (2 * sliceDet.x()); + slice.m_node = Slices.next(); + } + } + } + } + } +//----------------------------------------------------------------------------------- +//----------------------------------------------------------------------------------- + + } + + dd4hep::Position detectorLayerTrans(0., 0., 0.); + dd4hep::PlacedVolume detectorLayerPhys = BarrelVolume.placeVolume(BarrelDetectorLayerVolume, dd4hep::Transform3D(dd4hep::RotationZ(0.), detectorLayerTrans)); + detectorLayerPhys.addPhysVolID("layer", numBarrelLayer+1); + dd4hep::DetElement BarrelDetectorLayerDE(BarrelDE, "MSBarrelDetectorLayerDE" + numBarrelLayer+1, numBarrelLayer+1); + BarrelDetectorLayerDE.setPlacement(detectorLayerPhys); + BarrelDetectorLayerVolume.setVisAttributes(lcdd.visAttributes("no_vis")); + + } + +// ---------------------------------------// B A R R E L // R A D I A T O R S //------------------------------------------------ + + for (int numBarrelRadiatorLayer = 0; numBarrelRadiatorLayer < numBarrelRadiators; ++numBarrelRadiatorLayer){ + + double barrelRadiatorLayerRMin = radius + (numBarrelRadiatorLayer +1) * (2 * detectorVolumeThickness) + numBarrelRadiatorLayer * barrelRadiatorThickness; // I'm assuming that the yoke is following the detctor layer; one detector layer then -> one yoke layer. + double barrelRadiatorLayerRMax = barrelRadiatorLayerRMin + barrelRadiatorThickness; + double barrelRadiatorLayerRMid = (barrelRadiatorLayerRMin + barrelRadiatorLayerRMax)/2.0; + + dd4hep::PolyhedraRegular BarrelRadiatorLayer(numSides, barrelRadiatorLayerRMin, barrelRadiatorLayerRMax, barrelLength); + std::string barrelRadiatorEnvName = dd4hep::xml::_toString(numBarrelRadiatorLayer +1, "MS-BarrelRadiatorLayer%d"); + dd4hep::Volume BarrelRadiatorLayerVolume(barrelRadiatorEnvName , BarrelRadiatorLayer, mat); + + double barrelRadiatorSideLength = 2 * (barrelRadiatorLayerRMid - barrelRadiatorThickness/2.0)* std::tan(shapeAngle_radians); + double barrelRadiatorSideLength2 = 2 * (barrelRadiatorLayerRMid + barrelRadiatorThickness/2.0) * std::tan(shapeAngle_radians); + + for (int side = 0; side < numSides; ++side) { + int sideID = (numBarrelRadiatorLayer + 1) * 100 + (side +1); // to differentiated with the same side in different layers. + dd4hep::Trapezoid barrelRadiatorEnvelope(barrelLength/2.0, barrelLength/2.0, barrelRadiatorSideLength/2.0, barrelRadiatorSideLength2/2.0, barrelRadiatorThickness/2.0); + std::string barrelRadiatorEnvelopeName = dd4hep::xml::_toString(sideID, "MSBarrelRadiatorSide%d"); + dd4hep::Volume barrelRadiatorEnvVol(barrelRadiatorEnvelopeName, barrelRadiatorEnvelope, mat); + + double angle_degrees = shapeAngle * side; // Calculate the angle for each side + double angle_radians = angle_degrees * M_PI / 180.0; + + double barrelRadiatorXOffset = barrelRadiatorLayerRMid * std::cos(angle_radians+shapeAngle_radians); + double barrelRadiatorYOffset = barrelRadiatorLayerRMid * std::sin(angle_radians+shapeAngle_radians); + + dd4hep::RotationZ barrelRadiatorRotationZ(angle_radians+shapeAngle_radians); + dd4hep::RotationY barrelRadiatorRotationY(90.* dd4hep::degree); + + dd4hep::Rotation3D barrelRadiatorRotation = barrelRadiatorRotationZ * barrelRadiatorRotationY; + + double barrelRadiatorXPos = barrelRadiatorXOffset ; + double barrelRadiatorYPos = barrelRadiatorYOffset ; + double barrelRadiatorZPos = 0.0; + + dd4hep::Position barrelRadiatorEnvelopeTrans(barrelRadiatorXPos, barrelRadiatorYPos, barrelRadiatorZPos); + dd4hep::PlacedVolume barrelRadiatorEnvelopePhys = BarrelRadiatorLayerVolume.placeVolume(barrelRadiatorEnvVol, dd4hep::Transform3D(barrelRadiatorRotation, barrelRadiatorEnvelopeTrans)); + dd4hep::DetElement barrelRadiatorEnvelopeDE(detElement, barrelRadiatorEnvelopeName + "DE", sideID); + barrelRadiatorEnvelopeDE.setPlacement(barrelRadiatorEnvelopePhys); + barrelRadiatorEnvVol.setVisAttributes(lcdd, xmlDet.visStr()); + + // ----------------------------------------- Building the yokes ------------------ + + dd4hep::Trapezoid barrelRadiator(barrelLength/2.0, barrelLength/2.0, barrelRadiatorSideLength/2.0, barrelRadiatorSideLength2/2.0, barrelRadiatorThickness/2.0); + std::string barrelRadiatorName = dd4hep::xml::_toString(side, "barrelRadiator%d"); + dd4hep::Volume barrelRadiatorVol(barrelRadiatorName, barrelRadiator, barrelRadiatorMaterial); + + + dd4hep::Position barrelRadiatorTrans(0, 0, 0); + dd4hep::PlacedVolume barrelRadiatorPhys = barrelRadiatorEnvVol.placeVolume(barrelRadiatorVol, dd4hep::Transform3D(dd4hep::RotationY(0.), barrelRadiatorTrans)); + dd4hep::DetElement barrelRadiatorDE(barrelRadiatorEnvelopeDE, barrelRadiatorName + "DE", sideID); + barrelRadiatorDE.setPlacement(barrelRadiatorPhys); + barrelRadiatorVol.setVisAttributes(lcdd.visAttributes("yoke_vis")); + + } + + dd4hep::Position radiatorLayerTrans(0., 0., 0.); + dd4hep::PlacedVolume radiatorLayerPhys = BarrelVolume.placeVolume(BarrelRadiatorLayerVolume, dd4hep::Transform3D(dd4hep::RotationZ(0.), radiatorLayerTrans)); + dd4hep::DetElement BarrelRadiatorLayerDE(BarrelDE, "MSBarrel_RadiatorLayerDE" + numBarrelRadiatorLayer+1, numBarrelRadiatorLayer+1); + BarrelRadiatorLayerDE.setPlacement(radiatorLayerPhys); + BarrelRadiatorLayerVolume.setVisAttributes(lcdd.visAttributes("no_vis")); + + } + +// ------------------------------------------------------------------------------------------- +// ----------------------------------// E N D C A P //--------------------------------------- +//--------------------------------------- Endcap Detectors------------------------------------ + + std::string EndcapName; + dd4hep::Volume endcapVolume; + dd4hep::Position endcapTrans; + dd4hep::PlacedVolume endcapPhys; + dd4hep::DetElement EndcapDE; + + for (int endcapType = -1; endcapType < 2; ++endcapType){ + if (endcapType == 0) { + continue; // Skip the iteration when endcapType is 0 + } + EndcapName = dd4hep::xml::_toString(endcapType, "MS-Endcap%d"); + endcapVolume = dd4hep::Volume(EndcapName, EndcapEnv, mat); + endcapTrans = dd4hep::Position(0., 0., endcapType * endcapOffset); + endcapPhys = detectorVolume.placeVolume(endcapVolume, dd4hep::Transform3D(dd4hep::RotationZ(0.), endcapTrans)); + endcapPhys.addPhysVolID("type", endcapType); + EndcapDE = dd4hep::DetElement(detElement, "MSEndcapDE" + endcapType , endcapType); + EndcapDE.setPlacement(endcapPhys); + endcapVolume.setVisAttributes(lcdd.visAttributes("no_vis")); + + // ------------------ loop to create endcap layers ------------------ + + for (int numEndcapLayer = 0; numEndcapLayer < numEndcapDetectorLayers; ++numEndcapLayer){ + + double endcapLayerZOffset; + std::string endcapDetectorEnvelopeName; + double endcapDetectorEnvZPos; + + dd4hep::PolyhedraRegular endcapDetectorEnvelope(numSides, endcapDetectorLayerInnerRadius, endcapDetectorLayerOuterRadius, 2 * detectorVolumeThickness); + + endcapLayerZOffset = - EndcaptotalLength/2.0 + detectorVolumeThickness + numEndcapLayer * (2 * detectorVolumeThickness) + numEndcapLayer * endcapRadiatorThickness; // Automation of inner Z-Offset of different layers, taking into account that every detector layer is followed by a yoke(radiator) layer + endcapDetectorEnvelopeName = dd4hep::xml::_toString(numEndcapLayer+1, "MS-EndcapDetectorLayer%d"); + endcapDetectorEnvZPos = endcapLayerZOffset; + + + dd4hep::Volume endcapDetectorEnvVol(endcapDetectorEnvelopeName, endcapDetectorEnvelope, mat); + + double endcapDetectorEnvXPos = 0.0 ; + double endcapDetectorEnvYPos = 0.0 ; + + int detElementID = (numEndcapLayer < 0) ? numEndcapLayer + numEndcapDetectorLayers : numEndcapLayer + numEndcapDetectorLayers + 1; + + dd4hep::Position endcapDetectorEnvelopeTrans(endcapDetectorEnvXPos, endcapDetectorEnvYPos, endcapDetectorEnvZPos); + dd4hep::PlacedVolume endcapDetectorEnvelopePhys = endcapVolume.placeVolume(endcapDetectorEnvVol, dd4hep::Transform3D(dd4hep::RotationZ(0.), endcapDetectorEnvelopeTrans)); + dd4hep::DetElement endcapDetectorEnvelopeDE(EndcapDE, endcapDetectorEnvelopeName + "DE", detElementID); + endcapDetectorEnvelopeDE.setPlacement(endcapDetectorEnvelopePhys); + endcapDetectorEnvVol.setVisAttributes(lcdd, xmlDet.visStr()); + + // -------------------------- Building detector sides --------------------- + + for (int side = 0; side < numSides; ++side) { + + int sideID = (numEndcapLayer + 1) * 100 + (side +1); // to differentiated with the same side in different layers. + dd4hep::Trapezoid endcapDetectorSideTrap(endcapDetectorEnvZ/2.0, endcapDetectorEnvZ/2.0, endcapDetectorSideLength/2.0, endcapDetectorSideTrapLength/2.0, endcapDetectorSideTrapYLength/2.0); + dd4hep::Box endcapDetectorSideBox(endcapDetectorEnvZ/2.0, endcapDetectorSideBoxLength/2.0, endcapDetectorSideBoxYLength/2.0); + + double boxOffsetZ = endcapDetectorYLength/2.0; + + dd4hep::Position boxPos(0.0 , 0.0, boxOffsetZ); + dd4hep::Rotation3D boxRot(dd4hep::RotationY(0.0 * dd4hep::degree)); + + dd4hep::Transform3D boxTransform(boxRot, boxPos); + + //Combining two shapes by UnionSolid: the first shape is centralized and the second transform around the first.. + dd4hep::UnionSolid endcapDetectorSideEnvelope(endcapDetectorSideTrap, endcapDetectorSideBox, boxTransform); + std::string endcapDetectorSideEnvName = dd4hep::xml::_toString(sideID, "endcapDetectorSideEnv%d"); + dd4hep::Volume endcapDetectorSideEnvVol(endcapDetectorSideEnvName, endcapDetectorSideEnvelope, mat); + + double angle_degrees = shapeAngle * side; // Calculate the angle for each side + double angle_radians = angle_degrees * M_PI / 180.0; + + //double endcapDetectorMidRadius = endcapDetectorLayerInnerRadius + (endcapDetectorYLength /2.0); + double endcapDetectorTrapCenterRadius = endcapDetectorLayerInnerRadius + (endcapDetectorSideTrapYLength/2.0); + + double endcapDetectorXOffset = endcapDetectorTrapCenterRadius * std::cos(angle_radians+shapeAngle_radians); + double endcapDetectorYOffset = endcapDetectorTrapCenterRadius * std::sin(angle_radians+shapeAngle_radians); + + dd4hep::RotationZ endcapDetectorRotationZ(angle_radians+shapeAngle_radians); + dd4hep::Rotation3D endcapDetectorRotation = dd4hep::Rotation3D(endcapDetectorRotationZ); + + double endcapDetectorSideEnvXPos = endcapDetectorXOffset ; + double endcapDetectorSideEnvYPos = endcapDetectorYOffset ; + double endcapDetectorSideEnvZPos = - endcapDetectorEnvZ/2.0 ; + double endcapDetectorSideEnvZPos2 = endcapDetectorEnvZ/2.0; + + // --------- here I start to divide the two z-positions // by odd and even numbers + + dd4hep::Position endcapDetectorSideEnvTrans; + dd4hep::PlacedVolume endcapDetectorSideEnvPhys; + dd4hep::DetElement endcapDetectorSideEnvDE; + + if (side % 2 == 0) { + + endcapDetectorSideEnvTrans = dd4hep::Position(endcapDetectorSideEnvXPos, endcapDetectorSideEnvYPos, endcapDetectorSideEnvZPos); + endcapDetectorSideEnvPhys = endcapDetectorEnvVol.placeVolume(endcapDetectorSideEnvVol, dd4hep::Transform3D(endcapDetectorRotation * dd4hep::RotationY(90.0 * dd4hep::degree) , endcapDetectorSideEnvTrans)); + endcapDetectorSideEnvDE = dd4hep::DetElement(endcapDetectorEnvelopeDE, endcapDetectorSideEnvName + "DE", sideID); + endcapDetectorSideEnvDE.setPlacement(endcapDetectorSideEnvPhys); + endcapDetectorSideEnvVol.setVisAttributes(lcdd, xmlDet.visStr()); + + } else { + + endcapDetectorSideEnvTrans = dd4hep::Position(endcapDetectorSideEnvXPos, endcapDetectorSideEnvYPos, endcapDetectorSideEnvZPos2); + endcapDetectorSideEnvPhys = endcapDetectorEnvVol.placeVolume(endcapDetectorSideEnvVol, dd4hep::Transform3D(endcapDetectorRotation * dd4hep::RotationY(90.0 * dd4hep::degree) , endcapDetectorSideEnvTrans)); + endcapDetectorSideEnvDE = dd4hep::DetElement(endcapDetectorEnvelopeDE, endcapDetectorSideEnvName + "DE", sideID); + endcapDetectorSideEnvDE.setPlacement(endcapDetectorSideEnvPhys); + endcapDetectorSideEnvVol.setVisAttributes(lcdd, xmlDet.visStr()); + } + + // ----- dividing the trapezoid envelope to smaller pieces (rectangles) + + int numRectangles = endcapDetectorYLength / (2 * dimensions.z() - overlapZ); // numbers of the rectangles in each teapezoids.. depends on the number of the chambers that can be overlapped in Y direction + + for (int rectangle = 0; rectangle < (numRectangles + 1); ++rectangle) { + + double rectangleEnvX = endcapDetectorEnvZ/4.5; // dividing by 4.5 gets the best thickness for the recatngle to avoid any overlap ~ in our case the uRWELL the thickness is 26.667 mm which is 120/4.5. + double rectangleEnvY = (endcapDetectorLayerOuterRadius - rectangle * (2 * dimensions.y() - overlapY)) * std::tan(shapeAngle_radians) ; // without multiplying by 2 .. because it is the half length // it should be dimensions.x() instead of z, but in the endcap its perpendicular to usual dimension set + double rectangleEnvZ; + if (rectangle == numRectangles) { + rectangleEnvZ = (endcapRemainderZ * dimensions.z()) + clearance/4.0; + } else { + rectangleEnvZ = dimensions.z() + clearance/2.0; + } + + dd4hep::Box rectangleEnvelope(rectangleEnvX, rectangleEnvY, rectangleEnvZ); + std::string rectangleEnvelopeName; + if (rectangle == numRectangles) { + rectangleEnvelopeName = dd4hep::xml::_toString(rectangle, "rectangleRemainderEnvelope%d"); + } else { + rectangleEnvelopeName = dd4hep::xml::_toString(rectangle, "rectangleEnvelope%d"); + } + dd4hep::Volume rectangleEnvVol(rectangleEnvelopeName, rectangleEnvelope, mat); + + double rectangleEnvXPos = 0.0; + double rectangleEnvYPos = 0.0; + double rectangleEnvZPos; + if (rectangle == numRectangles) { + rectangleEnvZPos = endcapDetectorYLength/2.0 + ((1-endcapRemainderZ) * dimensions.z()) - (rectangle * (2 * dimensions.z() - overlapZ)) - clearance; + } else { + rectangleEnvZPos = endcapDetectorYLength/2.0 - (rectangle * (2 * dimensions.y() - overlapY)) - clearance; + } + + double yRotation = std::atan(rectangleEnvX / (rectangleEnvZ - (2 * overlapY))); + dd4hep::RotationY rotationY(yRotation); + + dd4hep::Position rectangeEnvelopeTrans(rectangleEnvXPos, rectangleEnvYPos, rectangleEnvZPos); + dd4hep::PlacedVolume rectangleEnvelopePhys = endcapDetectorSideEnvVol.placeVolume(rectangleEnvVol, dd4hep::Transform3D(rotationY, rectangeEnvelopeTrans)); + dd4hep::DetElement rectangleEnvelopeDE(endcapDetectorSideEnvDE, rectangleEnvelopeName + "DE", rectangle); // remember to loop over numEndcapDetectorLayers.. because now it still just one number. + rectangleEnvelopeDE.setPlacement(rectangleEnvelopePhys); + rectangleEnvVol.setVisAttributes(lcdd, xmlDet.visStr()); + + // ------------------------ start to build the chamber envelopes ------------------- + + int numChambersInRectangle = 2 * rectangleEnvY / (2 * dimensions.y() - overlapY); // number of the chambers in each rectangle + + for (int chamberIndex = 0; chamberIndex < (numChambersInRectangle + 1); chamberIndex++) { + + std::stringstream endcapNameStream; + endcapNameStream << "MuRWELL_Endcap_" << endcapIdCounter++; + std::string EndcapChamberName = endcapNameStream.str(); + + dd4hep::Box envelope; + if (rectangle == numRectangles) { + envelope = dd4hep::Box(dimensions.x(), dimensions.y(),endcapRemainderZ * dimensions.z()); + } else { + envelope = dd4hep::Box(dimensions.x(), dimensions.y(), dimensions.z()); + } + + dd4hep::Volume envVolume(EndcapChamberName, envelope, lcdd.material(dimensions.materialStr())); + + double rectangleRemainderY = std::fmod(2 * (rectangleEnvY - clearance), (2 * dimensions.y() - overlapY)) / (2 * dimensions.y()); + + dd4hep::Box rectangleRemainderYEnvelope; + if (rectangle == numRectangles) { + rectangleRemainderYEnvelope = dd4hep::Box(dimensions.x(), rectangleRemainderY * dimensions.y(), endcapRemainderZ * dimensions.z()); + } else { + rectangleRemainderYEnvelope = dd4hep::Box(dimensions.x(), rectangleRemainderY * dimensions.y(), dimensions.z()); + } + + dd4hep::Volume rectangleRemainderYEnvVolume(EndcapChamberName + "rectangleRemainderY", rectangleRemainderYEnvelope, lcdd.material(dimensions.materialStr())); + + double envYPos = (chamberIndex * 2 * dimensions.y()) - (overlapY * chamberIndex) + dimensions.y_offset() - rectangleEnvY + dimensions.y() + 0.005 ; // found that the positioning of the chambers inside the rectangle had an overlap with the mother volume ~ 45 um. + double rectangleRemainderREnvYPos = (chamberIndex * 2 * dimensions.y()) - (overlapY * chamberIndex) + dimensions.y_offset() - rectangleEnvY + rectangleRemainderY * dimensions.y() + 0.005; + + double zRotation = std::atan(dimensions.x() / (dimensions.z() - (2 * overlapZ))); + dd4hep::RotationZ chamberRotation(zRotation); + + double rectangleRemainderZRotation = std::atan(dimensions.x() / (rectangleRemainderY * dimensions.z() - (2 * overlapZ))); // Y and Z are reversed in local remainder + dd4hep::RotationZ rectangleRemainderRotationZ(rectangleRemainderZRotation); + + auto Slices = xmlElement.children(_Unicode(slice)); + auto numSlices = xmlElement.numChildren(_Unicode(slice), true); + dd4hep::xml::Handle_t slice(Slices.reset()); + int sensitiveSliceIndex = 0; + + // --- two cases : one for full chambers ---------------------------------------------- + + if (chamberIndex == numChambersInRectangle) { + + dd4hep::Position rectangleRemainderTrans(dimensions.x_offset(), rectangleRemainderREnvYPos, 0.0); + dd4hep::PlacedVolume rectangleRemainderEnvPhys = rectangleEnvVol.placeVolume(rectangleRemainderYEnvVolume, dd4hep::Transform3D(rectangleRemainderRotationZ , rectangleRemainderTrans)); + rectangleRemainderEnvPhys.addPhysVolID("chamber", endcapIdCounter); + dd4hep::DetElement rectangleRemainderEnvDE(rectangleEnvelopeDE, EndcapChamberName, endcapIdCounter); + rectangleRemainderEnvDE.setPlacement(rectangleRemainderEnvPhys); + rectangleRemainderYEnvVolume.setVisAttributes(lcdd, xmlDet.visStr()); + + // std::cout << "Adding detector element: " << detElement.name() << " to path: " << detElement.path() << std::endl; + double sliceXOffset = - dimensions.x(); + for (unsigned sliceIdx = 0; sliceIdx < numSlices; ++sliceIdx) { + dd4hep::xml::DetElement sliceDet = static_cast(slice); + dd4hep::Box sliceShape; + if (rectangle == numRectangles) { + sliceShape = dd4hep::Box(sliceDet.x(), rectangleRemainderY * dimensions.y(), endcapRemainderZ * dimensions.z()); + } else { + sliceShape = dd4hep::Box(sliceDet.x(), rectangleRemainderY * dimensions.y(), dimensions.z()); + } + std::string sliceName = dd4hep::xml::_toString(sliceIdx, "slice%d"); + dd4hep::Volume sliceVolume(sliceName, sliceShape, lcdd.material(slice.attr("material"))); + dd4hep::Position transSlice(sliceXOffset + sliceDet.x(), 0.0, 0.0); + dd4hep::PlacedVolume slicePlacedVolume = rectangleRemainderYEnvVolume.placeVolume(sliceVolume, dd4hep::Transform3D(dd4hep::RotationZ(0.), transSlice)); + + if (slice.hasAttr("vis")) { + sliceVolume.setVisAttributes(lcdd, sliceDet.visStr()); + } + if (slice.hasAttr("sensitive") && sliceDet.isSensitive()) { + dd4hep::xml::Dimension sdType(xmlElement.child(_U(sensitive))); + sensDet.setType(sdType.typeStr()); + sliceVolume.setSensitiveDetector(sensDet); + slicePlacedVolume.addPhysVolID("slice", sensitiveSliceIndex); + // dd4hep::printout(dd4hep::INFO,"Sensitive slice has been created at", name,EndcapChamberName); + sensitiveSliceIndex++; + } + // Increment the current x-offset by the width of the current slice + sliceXOffset += (2 * sliceDet.x()); + slice.m_node = Slices.next(); + } + + // ---------------- + } else { + + dd4hep::Position trans(dimensions.x_offset(), envYPos, 0.0); + dd4hep::PlacedVolume envPhys = rectangleEnvVol.placeVolume(envVolume, dd4hep::Transform3D(chamberRotation , trans)); + envPhys.addPhysVolID("chamber", endcapIdCounter); + dd4hep::DetElement envDE(rectangleEnvelopeDE, EndcapChamberName, endcapIdCounter); + envDE.setPlacement(envPhys); + envVolume.setVisAttributes(lcdd, xmlDet.visStr()); + + // std::cout << "Adding detector element: " << detElement.name() << " to path: " << detElement.path() << std::endl; + double sliceXOffset = - dimensions.x(); + for (unsigned sliceIdx = 0; sliceIdx < numSlices; ++sliceIdx) { + dd4hep::xml::DetElement sliceDet = static_cast(slice); + dd4hep::Box sliceShape; + if (rectangle == numRectangles) { + sliceShape = dd4hep::Box(sliceDet.x(), dimensions.y(), endcapRemainderZ * dimensions.z()); + } else { + sliceShape = dd4hep::Box(sliceDet.x(), dimensions.y(), dimensions.z()); + } + std::string sliceName = dd4hep::xml::_toString(sliceIdx, "slice%d"); + dd4hep::Volume sliceVolume(sliceName, sliceShape, lcdd.material(slice.attr("material"))); + dd4hep::Position transSlice(sliceXOffset + sliceDet.x(), 0.0, 0.0); + dd4hep::PlacedVolume slicePlacedVolume = envVolume.placeVolume(sliceVolume, dd4hep::Transform3D(dd4hep::RotationZ(0.), transSlice)); + + if (slice.hasAttr("vis")) { + sliceVolume.setVisAttributes(lcdd, sliceDet.visStr()); + } + if (slice.hasAttr("sensitive") && sliceDet.isSensitive()) { + dd4hep::xml::Dimension sdType(xmlElement.child(_U(sensitive))); + sensDet.setType(sdType.typeStr()); + sliceVolume.setSensitiveDetector(sensDet); + slicePlacedVolume.addPhysVolID("slice", sensitiveSliceIndex); + // dd4hep::printout(dd4hep::INFO,"Sensitive slice has been created at", name, EndcapChamberName); + sensitiveSliceIndex++; + } + // Increment the current x-offset by the width of the current slice + sliceXOffset += (2 * sliceDet.x()); + slice.m_node = Slices.next(); + } + } + } + } + } + } +// --------------------------------------Radiators-------------------------------------------- + + for (int numEndcapRadiatorLayer = 0; numEndcapRadiatorLayer < numEndcapRadiators; ++numEndcapRadiatorLayer){ + + double endcapRadiatorLayerZOffset = - EndcaptotalLength/2.0 + (endcapRadiatorThickness/2.0) + (numEndcapRadiatorLayer +1) * (2 * detectorVolumeThickness) + numEndcapRadiatorLayer * endcapRadiatorThickness; // Automation of inner Z-Offset of different layers, taking into account that every detector layer is followed by a yoke(radiator) layer + + dd4hep::PolyhedraRegular endcapRadiatorEnvelope(numSides, endcapRadiatorLayerInnerRadius, endcapRadiatorLayerOuterRadius, endcapRadiatorThickness); + std::string endcapRadiatorEnvelopeName = dd4hep::xml::_toString(numEndcapRadiatorLayer+1, "MS-EndcapRadiatorLayer%d"); + dd4hep::Volume endcapRadiatorEnvVol(endcapRadiatorEnvelopeName, endcapRadiatorEnvelope, mat); + + double endcapRadiatorEnvXPos = 0.0 ; + double endcapRadiatorEnvYPos = 0.0 ; + double endcapRadiatorEnvZPos = endcapRadiatorLayerZOffset; + + dd4hep::Position endcapRadiatorEnvelopeTrans(endcapRadiatorEnvXPos, endcapRadiatorEnvYPos, endcapRadiatorEnvZPos); + dd4hep::PlacedVolume endcapRadiatorEnvelopePhys = endcapVolume.placeVolume(endcapRadiatorEnvVol, dd4hep::Transform3D(dd4hep::RotationZ(0.), endcapRadiatorEnvelopeTrans)); + dd4hep::DetElement endcapRadiatorEnvelopeDE(EndcapDE, endcapRadiatorEnvelopeName + "DE", numEndcapRadiatorLayer+1); + endcapRadiatorEnvelopeDE.setPlacement(endcapRadiatorEnvelopePhys); + endcapRadiatorEnvVol.setVisAttributes(lcdd, xmlDet.visStr()); + + // ----------------Building radiator sides------------------ + + for (int side = 0; side < numSides; ++side) { + + int sideID = (numEndcapRadiatorLayer + 1) * 100 + (side +1); // to differentiated with the same side in different layers. + dd4hep::Trapezoid endcapRadiator(endcapRadiatorThickness/2.0, endcapRadiatorThickness/2.0, endcapRadiatorSideLength/2.0, endcapRadiatorSideLength2/2.0, endcapYLength/2.0); + std::string endcapRadiatorName = dd4hep::xml::_toString(sideID, "endcapRadiator%d"); + dd4hep::Volume endcapRadiatorVol(endcapRadiatorName, endcapRadiator, endcapRadiatorMaterial); + + double angle_degrees = shapeAngle * side; // Calculate the angle for each side + double angle_radians = angle_degrees * M_PI / 180.0; //radian angle for each side (rotating angle) + + double endcapRadiatorMidRadius = endcapRadiatorLayerInnerRadius + (endcapYLength /2.0); + + double endcapRadiatorXOffset = endcapRadiatorMidRadius * std::cos(angle_radians+shapeAngle_radians); + double endcapRadiatorYOffset = endcapRadiatorMidRadius * std::sin(angle_radians+shapeAngle_radians); + + dd4hep::RotationZ endcapRadiatorRotationZ(angle_radians+shapeAngle_radians); + dd4hep::Rotation3D endcapRadiatorRotation = dd4hep::Rotation3D(endcapRadiatorRotationZ); + + double endcapRadiatorXPos = endcapRadiatorXOffset ; + double endcapRadiatorYPos = endcapRadiatorYOffset ; + double endcapRadiatorZPos = 0.0; + + dd4hep::Position endcapRadiatorTrans(endcapRadiatorXPos, endcapRadiatorYPos, endcapRadiatorZPos); + dd4hep::PlacedVolume endcapRadiatorPhys = endcapRadiatorEnvVol.placeVolume(endcapRadiatorVol, dd4hep::Transform3D(endcapRadiatorRotation * dd4hep::RotationY(90.* dd4hep::degree), endcapRadiatorTrans)); + dd4hep::DetElement endcapRadiatorDE(endcapRadiatorEnvelopeDE, endcapRadiatorName + "DE", sideID); + endcapRadiatorDE.setPlacement(endcapRadiatorPhys); + endcapRadiatorVol.setVisAttributes(lcdd.visAttributes("yoke_vis")); + + } + } + } + // ------------------------------------------------------------------------------------------- + dd4hep::Position detectorTrans(0., 0., 0.); + dd4hep::PlacedVolume detectorPhys = experimentalHall.placeVolume(detectorVolume, dd4hep::Transform3D(dd4hep::RotationZ(shapeAngle_radians), detectorTrans)); + detectorPhys.addPhysVolID("system", xmlDet.id()); + detElement.setPlacement(detectorPhys); + detectorVolume.setVisAttributes(lcdd.visAttributes("no_vis")); + return detElement; +} + +DECLARE_DETELEMENT(muonSystemMuRWELL_o1_v01, createmuonSystemMuRWELL_o1_v01)