From 8e9f859489bb08e07d6ac0cdae61628b6a684265 Mon Sep 17 00:00:00 2001 From: Brieuc Francois Date: Tue, 12 Dec 2023 14:48:27 +0100 Subject: [PATCH 01/29] [ALLEGRO] Fix to be able to run with ddsim (#311) --- FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/SimplifiedDriftChamber.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/SimplifiedDriftChamber.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/SimplifiedDriftChamber.xml index 11586a5df..9d13d0176 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/SimplifiedDriftChamber.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/SimplifiedDriftChamber.xml @@ -45,7 +45,7 @@ - + Dimensions for the drift chamber From 81c699191ca5e291d2969867bce2b01e23dd7690 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Mon, 20 Nov 2023 17:29:38 +0100 Subject: [PATCH 02/29] add xml for calibration --- ...alBarrel_thetamodulemerged_calibration.xml | 136 ++++++++++++++++++ ..._ECalBarrel_thetamodulemerged_upstream.xml | 136 ++++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/FCCee_ECalBarrel_thetamodulemerged_calibration.xml create mode 100644 FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/FCCee_ECalBarrel_thetamodulemerged_upstream.xml diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/FCCee_ECalBarrel_thetamodulemerged_calibration.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/FCCee_ECalBarrel_thetamodulemerged_calibration.xml new file mode 100644 index 000000000..be8770709 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/FCCee_ECalBarrel_thetamodulemerged_calibration.xml @@ -0,0 +1,136 @@ + + + + + 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. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/FCCee_ECalBarrel_thetamodulemerged_upstream.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/FCCee_ECalBarrel_thetamodulemerged_upstream.xml new file mode 100644 index 000000000..8c96a5939 --- /dev/null +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/FCCee_ECalBarrel_thetamodulemerged_upstream.xml @@ -0,0 +1,136 @@ + + + + + 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. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 53adc24e0c3593b141b29f6ab745a409b926ae73 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Mon, 20 Nov 2023 17:32:44 +0100 Subject: [PATCH 03/29] fix comments inside ALLEGRO xml --- FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ALLEGRO_o1_v02.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ALLEGRO_o1_v02.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ALLEGRO_o1_v02.xml index 49c76c53d..ff4266dd9 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ALLEGRO_o1_v02.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/ALLEGRO_o1_v02.xml @@ -3,14 +3,14 @@ xmlns:xs="http://www.w3.org/2001/XMLSchema" xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd"> - - Master compact file describing the latest developments of the FCCee IDEA detector concept with a LAr calorimeter. + Master compact file describing the latest developments of the FCCee ALLEGRO detector concept. From 40583653b1ad8b3e2df84c9fd190d0c9aa695a18 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Mon, 20 Nov 2023 17:33:25 +0100 Subject: [PATCH 04/29] fix header ifdef --- .../FCCSWGridModuleThetaMergedHandle_k4geo.h | 4 ++-- .../detectorSegmentations/FCCSWGridModuleThetaMerged_k4geo.h | 4 ++-- .../detectorSegmentations/FCCSWGridPhiEtaHandle_k4geo.h | 4 ++-- .../include/detectorSegmentations/FCCSWGridPhiEta_k4geo.h | 4 ++-- .../detectorSegmentations/FCCSWGridPhiThetaHandle_k4geo.h | 4 ++-- .../include/detectorSegmentations/FCCSWGridPhiTheta_k4geo.h | 4 ++-- .../include/detectorSegmentations/GridEtaHandle_k4geo.h | 4 ++-- .../include/detectorSegmentations/GridEta_k4geo.h | 4 ++-- .../include/detectorSegmentations/GridThetaHandle_k4geo.h | 4 ++-- .../include/detectorSegmentations/GridTheta_k4geo.h | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/detectorSegmentations/include/detectorSegmentations/FCCSWGridModuleThetaMergedHandle_k4geo.h b/detectorSegmentations/include/detectorSegmentations/FCCSWGridModuleThetaMergedHandle_k4geo.h index c0b79ea89..cdbb30223 100644 --- a/detectorSegmentations/include/detectorSegmentations/FCCSWGridModuleThetaMergedHandle_k4geo.h +++ b/detectorSegmentations/include/detectorSegmentations/FCCSWGridModuleThetaMergedHandle_k4geo.h @@ -1,5 +1,5 @@ -#ifndef DD4HEP_DDCORE_GRIDMODULETHETAMERGED_H -#define DD4HEP_DDCORE_GRIDMODULETHETAMERGED_H 1 +#ifndef DETECTORSEGMENTATIONS_FCCSWGRIDMODULETHETAMERGEDHANDLE_K4GEO_H +#define DETECTORSEGMENTATIONS_FCCSWGRIDMODULETHETAMERGEDHANDLE_K4GEO_H // FCCSW #include "detectorSegmentations/FCCSWGridModuleThetaMerged_k4geo.h" diff --git a/detectorSegmentations/include/detectorSegmentations/FCCSWGridModuleThetaMerged_k4geo.h b/detectorSegmentations/include/detectorSegmentations/FCCSWGridModuleThetaMerged_k4geo.h index 796ba400d..98fb122ca 100644 --- a/detectorSegmentations/include/detectorSegmentations/FCCSWGridModuleThetaMerged_k4geo.h +++ b/detectorSegmentations/include/detectorSegmentations/FCCSWGridModuleThetaMerged_k4geo.h @@ -1,5 +1,5 @@ -#ifndef DETSEGMENTATION_FCCSWGridModuleThetaMerged_k4geo_H -#define DETSEGMENTATION_FCCSWGridModuleThetaMerged_k4geo_H +#ifndef DETECTORSEGMENTATIONS_FCCSWGridModuleThetaMerged_k4geo_H +#define DETECTORSEGMENTATIONS_FCCSWGridModuleThetaMerged_k4geo_H // FCCSW #include "detectorSegmentations/GridTheta_k4geo.h" diff --git a/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiEtaHandle_k4geo.h b/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiEtaHandle_k4geo.h index cd53e01fa..286c97f72 100644 --- a/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiEtaHandle_k4geo.h +++ b/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiEtaHandle_k4geo.h @@ -1,5 +1,5 @@ -#ifndef DD4HEP_DDCORE_GRIDPHIETA_H -#define DD4HEP_DDCORE_GRIDPHIETA_H 1 +#ifndef DETECTORSEGMENTATIONS_GRIDPHIETAHANDLE_K4GEO_H +#define DETECTORSEGMENTATIONS_GRIDPHIETAHANDLE_K4GEO_H // FCCSW #include "detectorSegmentations/FCCSWGridPhiEta_k4geo.h" diff --git a/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiEta_k4geo.h b/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiEta_k4geo.h index 7f80185a3..8c4336262 100644 --- a/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiEta_k4geo.h +++ b/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiEta_k4geo.h @@ -1,5 +1,5 @@ -#ifndef DETSEGMENTATION_GRIDPHIETA_H -#define DETSEGMENTATION_GRIDPHIETA_H +#ifndef DETECTORSEGMENTATIONS_GRIDPHIETA_K4GEO_H +#define DETECTORSEGMENTATIONS_GRIDPHIETA_K4GEO_H // FCCSW #include "detectorSegmentations/GridEta_k4geo.h" diff --git a/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiThetaHandle_k4geo.h b/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiThetaHandle_k4geo.h index efbfbf8da..a5546a846 100644 --- a/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiThetaHandle_k4geo.h +++ b/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiThetaHandle_k4geo.h @@ -1,5 +1,5 @@ -#ifndef DD4HEP_DDCORE_GRIDPHITHETA_H -#define DD4HEP_DDCORE_GRIDPHITHETA_H 1 +#ifndef DETECTORSEGMENTATIONS_GRIDPHITHETAHANDLE_K4GEO_H +#define DETECTORSEGMENTATIONS_GRIDPHITHETAHANDLE_K4GEO_H // FCCSW #include "detectorSegmentations/FCCSWGridPhiTheta_k4geo.h" diff --git a/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiTheta_k4geo.h b/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiTheta_k4geo.h index cc1d0c31d..aae4bab10 100644 --- a/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiTheta_k4geo.h +++ b/detectorSegmentations/include/detectorSegmentations/FCCSWGridPhiTheta_k4geo.h @@ -1,5 +1,5 @@ -#ifndef DETSEGMENTATION_GRIDPHITHETA_H -#define DETSEGMENTATION_GRIDPHITHETA_H +#ifndef DETECTORSEGMENTATIONS_GRIDPHITHETA_K4GEO_H +#define DETECTORSEGMENTATIONS_GRIDPHITHETA_K4GEO_H // FCCSW #include "detectorSegmentations/GridTheta_k4geo.h" diff --git a/detectorSegmentations/include/detectorSegmentations/GridEtaHandle_k4geo.h b/detectorSegmentations/include/detectorSegmentations/GridEtaHandle_k4geo.h index 961f46025..787c53e23 100644 --- a/detectorSegmentations/include/detectorSegmentations/GridEtaHandle_k4geo.h +++ b/detectorSegmentations/include/detectorSegmentations/GridEtaHandle_k4geo.h @@ -1,5 +1,5 @@ -#ifndef DD4HEP_DDCORE_GRIDETA_H -#define DD4HEP_DDCORE_GRIDETA_H 1 +#ifndef DETECTORSEGMENTATIONS_GRIDETAHANDLE_K4GEO_H +#define DETECTORSEGMENTATIONS_GRIDETAHANDLE_K4GEO_H // FCCSW #include "detectorSegmentations/GridEta_k4geo.h" diff --git a/detectorSegmentations/include/detectorSegmentations/GridEta_k4geo.h b/detectorSegmentations/include/detectorSegmentations/GridEta_k4geo.h index 29cd8dabd..ec4270f79 100644 --- a/detectorSegmentations/include/detectorSegmentations/GridEta_k4geo.h +++ b/detectorSegmentations/include/detectorSegmentations/GridEta_k4geo.h @@ -1,5 +1,5 @@ -#ifndef DETSEGMENTATION_GRIDETA_H -#define DETSEGMENTATION_GRIDETA_H +#ifndef DETECTORSEGMENTATIONS_GRIDETA_K4GEO_H +#define DETECTORSEGMENTATIONS_GRIDETA_K4GEO_H #include "DDSegmentation/Segmentation.h" diff --git a/detectorSegmentations/include/detectorSegmentations/GridThetaHandle_k4geo.h b/detectorSegmentations/include/detectorSegmentations/GridThetaHandle_k4geo.h index 923406665..9f97d1b63 100644 --- a/detectorSegmentations/include/detectorSegmentations/GridThetaHandle_k4geo.h +++ b/detectorSegmentations/include/detectorSegmentations/GridThetaHandle_k4geo.h @@ -1,5 +1,5 @@ -#ifndef DD4HEP_DDCORE_GRIDTHETA_H -#define DD4HEP_DDCORE_GRIDTHETA_H 1 +#ifndef DETECTORSEGMENTATIONS_GRIDTHETAHANDLE_K4GEO_H +#define DETECTORSEGMENTATIONS_GRIDTHETAHANDLE_K4GEO_H // FCCSW #include "detectorSegmentations/GridTheta_k4geo.h" diff --git a/detectorSegmentations/include/detectorSegmentations/GridTheta_k4geo.h b/detectorSegmentations/include/detectorSegmentations/GridTheta_k4geo.h index 84236c9db..0198e9c7b 100644 --- a/detectorSegmentations/include/detectorSegmentations/GridTheta_k4geo.h +++ b/detectorSegmentations/include/detectorSegmentations/GridTheta_k4geo.h @@ -1,5 +1,5 @@ -#ifndef DETSEGMENTATION_GRIDTHETA_H -#define DETSEGMENTATION_GRIDTHETA_H +#ifndef DETECTORSEGMENTATIONS_GRIDTHETA_K4GEO_H +#define DETECTORSEGMENTATIONS_GRIDTHETA_K4GEO_H #include "DDSegmentation/Segmentation.h" From 38163f0ff0af3b2e42f1fc619a324d52d1d61433 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Mon, 20 Nov 2023 17:34:40 +0100 Subject: [PATCH 05/29] update HCAL readout to theta projectivity for FCCee --- .../FCCee_HCalBarrel_TileCal.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/FCCee_HCalBarrel_TileCal.xml b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/FCCee_HCalBarrel_TileCal.xml index 0acecdb1d..714fffbe1 100644 --- a/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/FCCee_HCalBarrel_TileCal.xml +++ b/FCCee/ALLEGRO/compact/ALLEGRO_o1_v02/FCCee_HCalBarrel_TileCal.xml @@ -45,22 +45,22 @@ - - system:4,layer:5,row:9,eta:9,phi:10 + + system:4,layer:5,row:9,theta:9,phi:10 - - - system:4,layer:5,eta:9,phi:10 + + + system:4,layer:5,theta:9,phi:10 - - - system:4,layer:5,row:9,eta:0,phi:10 + + + system:4,layer:5,row:9,theta:0,phi:10 - + From e8f48719a746a322243dfad340dab3d9265fe493 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Mon, 20 Nov 2023 17:37:09 +0100 Subject: [PATCH 06/29] update README for calorimetr --- detector/calorimeter/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detector/calorimeter/README.md b/detector/calorimeter/README.md index e99fa66f4..f7efc63b6 100644 --- a/detector/calorimeter/README.md +++ b/detector/calorimeter/README.md @@ -12,7 +12,7 @@ The documentation about its usage is [here](../../doc/detector/calorimeter/ECalB Original version taken from [FCCDetectors](https://github.com/HEP-FCC/FCCDetectors/blob/main/Detector/DetFCChhECalInclined/src/ECalBarrelInclined_geo.cpp). ### o1_v02 -New version adapted to the theta segmentation with the possibility to have different number of cell merged per layer. The main difference is that now one has to set `ECalBarrelNumLayers` and `ECalBarrelNumPlanes` in the xml while before it was just dynamically computed based on other xml parameters (also, to avoid silent mistakes, the number from the xml and the one computed dynamically must match). +New version, with module-theta based segmentation. In each layer adjacent cells along theta or module directions can be grouped together, with possibly different merging per layer. This is specified with the `mergedCells_Theta` and `mergedModules` vectors in the `segmentation` tag of the xml file. The baseline grouping in theta is by four in all layers except L1 (the strip layer). The baseline grouping in module direction is by two in all layers. The LAr gap has also been slightly adjusted to bring back the number of modules to 1536 (it was 1545 before). The segmentation class needs to know the number of modules, which is passed via the `nModules` parameter of the `segmentation` tag. To ensure that number of modules and layers (length of the mergedXXX vectors) are consistent with number of modules and layers of the detector, the xml defines `ECalBarrelNumLayers` and `ECalBarrelNumPlanes`, and the c++ file doing the detector construction checks that the number of planes and layers calculated dynamically from other parameters matches that in the xml (if not, the code will crash). ## CaloDisks This sub-detector makes calorimeter endcaps (original and reflected). It is used in ALLEGRO detector concept. From d0118c533af5ab2e350fdb3167ea5ec0bac36555 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Mon, 20 Nov 2023 17:41:03 +0100 Subject: [PATCH 07/29] add code with helper functions for segmentation --- CMakeLists.txt | 1 + detectorCommon/CMakeLists.txt | 30 + .../include/detectorCommon/DetUtils_k4geo.h | 200 ++++++ detectorCommon/src/DetUtils_k4geo.cpp | 600 ++++++++++++++++++ 4 files changed, 831 insertions(+) create mode 100644 detectorCommon/CMakeLists.txt create mode 100644 detectorCommon/include/detectorCommon/DetUtils_k4geo.h create mode 100644 detectorCommon/src/DetUtils_k4geo.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a13ada8a..384999510 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,7 @@ find_package( Geant4 REQUIRED ) find_package( LCIO REQUIRED) add_subdirectory(detectorSegmentations) +add_subdirectory(detectorCommon) file(GLOB sources ./detector/tracker/*.cpp diff --git a/detectorCommon/CMakeLists.txt b/detectorCommon/CMakeLists.txt new file mode 100644 index 000000000..4bc3abc9d --- /dev/null +++ b/detectorCommon/CMakeLists.txt @@ -0,0 +1,30 @@ +################################################################################ +# Package: detectorCommon +################################################################################ + +file(GLOB sources src/*.cpp) +add_library(detectorCommon SHARED ${sources}) +target_link_libraries(detectorCommon DD4hep::DDCore DD4hep::DDG4 detectorSegmentations) +target_include_directories(detectorCommon + PUBLIC + $ + $ +) + +file(GLOB headers include/detectorCommon/*.h) +set_target_properties(detectorCommon PROPERTIES PUBLIC_HEADER "${headers}") + +install(TARGETS detectorCommon + EXPORT ${PROJECT_NAME}Targets + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib + PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_PREFIX}/include/detectorCommon" + COMPONENT dev) + + +dd4hep_generate_rootmap(detectorCommon) + +#include(CTest) +#gaudi_add_test(DumpSimpleBox +# WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} +# FRAMEWORK tests/dumpSimpleBox.py) diff --git a/detectorCommon/include/detectorCommon/DetUtils_k4geo.h b/detectorCommon/include/detectorCommon/DetUtils_k4geo.h new file mode 100644 index 000000000..04c1f93e6 --- /dev/null +++ b/detectorCommon/include/detectorCommon/DetUtils_k4geo.h @@ -0,0 +1,200 @@ +#ifndef DETECTORCOMMON_DETUTILS_H +#define DETECTORCOMMON_DETUTILS_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 utils { +dd4hep::xml::Component getNodeByStrAttr(const dd4hep::xml::Handle_t& mother, const std::string& nodeName, + const std::string& attrName, const std::string& attrValue); + +/// try to get attribute with double value, return defaultValue if attribute not found +double getAttrValueWithFallback(const dd4hep::xml::Component& node, const std::string& attrName, + const double& defaultValue); + +/** Retrieves the cellID based on the position of the step and the detector segmentation. + * @param aSeg Handle to the segmentation of the volume. + * @param aStep Step in which particle deposited the energy. + * @param aPreStepPoint Flag indicating if the position of the deposit is the beginning of the step (default) + * or the middle of the step. + */ + +uint64_t cellID(const dd4hep::Segmentation& aSeg, const G4Step& aStep, bool aPreStepPoint = true); + +/** Get number of possible combinations of bit fields for determination of neighbours. + * @param[in] aN number of field names. + * @param[in] aK length of bit fields included for index search. + * return vector of possible combinations of field values. + */ + +std::vector> combinations(int N, int K); + +/** Get number of possible permutations for certain combination of bit field indeces. + * @param[in] aN number of field names. + * return vector of permuations for certain field values. + */ + +std::vector> permutations(int K); + +/** Get true field value of neighbour in cyclic bit field + * @param[in] aCyclicId field value of neighbour + * @param[in] aFieldExtremes Minimal and Maximal values of the fields. + * return field value for neighbour in cyclic bit field + */ + +int cyclicNeighbour(int aCyclicId, std::pair aFieldExtremes); + +/** Get neighbours in many dimensions. + * @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. + * @param[in] aDiagonal If diagonal neighbours should be included (all combinations of fields). + * return Vector of neighbours. + */ +std::vector neighbours(const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, + const std::vector& aFieldNames, + const std::vector>& aFieldExtremes, + uint64_t aCellId, + const std::vector& aFieldCyclic = {false, false, false, false}, + bool aDiagonal = true); + +/** Special version of the 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. + * @param[in] aDiagonal If diagonal neighbours should be included (all combinations of fields). + * return Vector of neighbours. + */ +std::vector neighbours_ModuleThetaMerged(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, + const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, + const std::vector& aFieldNames, + const std::vector>& aFieldExtremes, + uint64_t aCellId, + bool aDiagonal = false); + +/** Get minimal and maximal values that can be decoded in the fields of the bitfield. + * @param[in] aDecoder Handle to the bitfield decoder. + * @param[in] aFieldNames Names of the fields for which extremes are found. + * return Vector of pairs (min,max) + */ +std::vector> bitfieldExtremes(const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, + const std::vector& aFieldNames); + +/** Get the half widths of the box envelope (TGeoBBox). + * @param[in] aVolumeId The volume ID. + * return Half-widths of the volume (x,y,z). + */ +CLHEP::Hep3Vector envelopeDimensions(uint64_t aVolumeId); + +/** Get the dimensions of a tube (TGeoConeSeg). + * @param[in] aVolumeId The volume ID. + * return Dimensions of the tube (rmin, rmax, z(half-length)). + */ +CLHEP::Hep3Vector tubeDimensions(uint64_t aVolumeId); + +/** Get the dimensions of a cone (TGeoCone). + * @param[in] aVolumeId The volume ID. + * return Dimensions of the cone (rmin, rmax, z(half-length)). + */ +CLHEP::Hep3Vector coneDimensions(uint64_t aVolumeId); + +/** Get the extrema in pseudorapidity of a tube or cone volume. + * @param[in] aVolumeId The volume ID. + * return Pseudorapidity extrema (eta_min, eta_max). + */ +std::array tubeEtaExtremes(uint64_t aVolumeId); + +/** Get the extrema in pseudorapidity of an envelope. + * @param[in] aVolumeId The volume ID. + * return Pseudorapidity extrema (eta_min, eta_max). + */ +std::array envelopeEtaExtremes(uint64_t aVolumeId); + +/** Get the extrema in pseudorapidity of a volume. First try to match tube or cone, if it fails use an envelope shape. + * @param[in] aVolumeId The volume ID. + * return Pseudorapidity extrema (eta_min, eta_max). + */ +std::array volumeEtaExtremes(uint64_t aVolumeId); + +/** Get the number of cells for the volume and a given Cartesian XY segmentation. + * For an example see: Test/TestReconstruction/tests/options/testcellcountingXYZ.py. + * @warning No offset in segmentation is currently taken into account. + * @param[in] aVolumeId The volume for which the cells are counted. + * @param[in] aSeg Handle to the segmentation of the volume. + * return Array of the number of cells in (X, Y). + */ +std::array numberOfCells(uint64_t aVolumeId, const dd4hep::DDSegmentation::CartesianGridXY& aSeg); + +/** Get the number of cells for the volume and a given Cartesian XYZ segmentation. + * For an example see: Test/TestReconstruction/tests/options/testcellcountingXYZ.py. + * @warning No offset in segmentation is currently taken into account. + * @param[in] aVolumeId The volume for which the cells are counted. + * @param[in] aSeg Handle to the segmentation of the volume. + * return Array of the number of cells in (X, Y, Z). + */ +std::array numberOfCells(uint64_t aVolumeId, const dd4hep::DDSegmentation::CartesianGridXYZ& aSeg); + +/** Get the number of cells for the volume and a given Phi-Eta / Phi-Theta / Module-Theta segmentation. + * It is assumed that the volume has a cylindrical shape (and full azimuthal coverage) + * and that it is centred at (0,0,0). + * For an example see: Test/TestReconstruction/tests/options/testcellcountingPhiEta.py. + * @warning No offset in segmentation is currently taken into account. + * @param[in] aVolumeId The volume for which the cells are counted. + * @param[in] aSeg Handle to the segmentation of the volume. + * return Array of the number of cells in (phi, eta) / (phi, theta) / (module, theta) and the minimum eta / theta ID. + */ +std::array numberOfCells(uint64_t aVolumeId, const dd4hep::DDSegmentation::FCCSWGridPhiEta_k4geo& aSeg); +std::array numberOfCells(uint64_t aVolumeId, const dd4hep::DDSegmentation::FCCSWGridPhiTheta_k4geo& aSeg); +std::array numberOfCells(uint64_t aVolumeId, const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg); + +/** Get the number of cells for the volume and a given R-phi segmentation. + * It is assumed that the volume has a cylindrical shape - TGeoTube (and full azimuthal coverage) + * and that it is centred at (0,0,0). + * For an example see: Test/TestReconstruction/tests/options/testcellcountingRPhi.py. + * @warning No offset in segmentation is currently taken into account. + * @param[in] aVolumeId The volume for which the cells are counted. + * @param[in] aSeg Handle to the segmentation of the volume. + * return Array of the number of cells in (r, phi). + */ +std::array numberOfCells(uint64_t aVolumeId, const dd4hep::DDSegmentation::PolarGridRPhi& aSeg); + +/** Get the number of the volumes containing a given name. + * For an example see: Test/TestReconstruction/tests/options/testcellcountingXYZ.py. + * @param[in] aHighestVolume The top volume in the geometry. + * @param[in] aMatchName Name (or its part) of the volume. + * return Number of the volumes. + */ +unsigned int countPlacedVolumes(TGeoVolume* aHighestVolume, const std::string& aMatchName); +} +} +#endif /* DETCOMMON_DETUTILS_H */ diff --git a/detectorCommon/src/DetUtils_k4geo.cpp b/detectorCommon/src/DetUtils_k4geo.cpp new file mode 100644 index 000000000..711118248 --- /dev/null +++ b/detectorCommon/src/DetUtils_k4geo.cpp @@ -0,0 +1,600 @@ +#include "detectorCommon/DetUtils_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 utils { +dd4hep::xml::Component getNodeByStrAttr(const dd4hep::xml::Handle_t& mother, const std::string& nodeName, + const std::string& attrName, const std::string& attrValue) { + for (dd4hep::xml::Collection_t xCompColl(mother, nodeName.c_str()); nullptr != xCompColl; ++xCompColl) { + if (xCompColl.attr(attrName.c_str()) == attrValue) { + return static_cast(xCompColl); + } + } + // in case there was no xml daughter with matching name + return dd4hep::xml::Component(nullptr); +} + +double getAttrValueWithFallback(const dd4hep::xml::Component& node, const std::string& attrName, + const double& defaultValue) { + if (node.hasAttr(_Unicode(attrName.c_str()))) { + return node.attr(attrName.c_str()); + } else { + return defaultValue; + } +} + +uint64_t cellID(const dd4hep::Segmentation& aSeg, const G4Step& aStep, bool aPreStepPoint) { + dd4hep::sim::Geant4VolumeManager volMgr = dd4hep::sim::Geant4Mapping::instance().volumeManager(); + dd4hep::VolumeID volID = volMgr.volumeID(aStep.GetPreStepPoint()->GetTouchable()); + if (aSeg.isValid()) { + G4ThreeVector global; + if (aPreStepPoint) { + global = aStep.GetPreStepPoint()->GetPosition(); + } else { + global = 0.5 * (aStep.GetPreStepPoint()->GetPosition() + aStep.GetPostStepPoint()->GetPosition()); + } + G4ThreeVector local = + aStep.GetPreStepPoint()->GetTouchable()->GetHistory()->GetTopTransform().TransformPoint(global); + dd4hep::Position loc(local.x() * MM_2_CM, local.y() * MM_2_CM, local.z() * MM_2_CM); + dd4hep::Position glob(global.x() * MM_2_CM, global.y() * MM_2_CM, global.z() * MM_2_CM); + dd4hep::VolumeID cID = aSeg.cellID(loc, glob, volID); + return cID; + } + return volID; +} + +std::vector> combinations(int N, int K) { + std::vector> indexes; + std::string bitmask(K, 1); // K leading 1's + bitmask.resize(N, 0); // N-K trailing 0's + // permute bitmask + do { + std::vector tmp; + for (int i = 0; i < N; ++i) { // [0..N-1] integers + if (bitmask[i]) { + tmp.push_back(i); + } + } + indexes.push_back(tmp); + } while (std::prev_permutation(bitmask.begin(), bitmask.end())); + return indexes; +} + +std::vector> permutations(int K) { + std::vector> indexes; + int N = pow(2, K); // number of permutations with repetition of 2 numbers (-1,1) + for (int i = 0; i < N; i++) { + // permutation = binary representation of i + std::vector tmp; + tmp.assign(K, 0); + uint res = i; + // dec -> bin + for (int j = 0; j < K; j++) { + tmp[K - 1 - j] = -1 + 2 * (res % 2); + res = floor(res / 2); + } + indexes.push_back(tmp); + } + return indexes; +} + +// use it for field module/phi +int cyclicNeighbour(int aCyclicId, std::pair aFieldExtremes) { + int nBins = aFieldExtremes.second - aFieldExtremes.first + 1; + if (aCyclicId < aFieldExtremes.first) { + return (aFieldExtremes.second + 1 - ((aFieldExtremes.first - aCyclicId) % nBins) ); + } else if (aCyclicId > aFieldExtremes.second) { + return ( ((aCyclicId - aFieldExtremes.first) % nBins) + aFieldExtremes.first) ; + } + return aCyclicId; +} + +std::vector neighbours(const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, + const std::vector& aFieldNames, + const std::vector>& aFieldExtremes, uint64_t aCellId, + const std::vector& aFieldCyclic, bool aDiagonal) { + std::vector neighbours; + dd4hep::DDSegmentation::CellID cID = aCellId; + for (uint itField = 0; itField < aFieldNames.size(); itField++) { + const auto& field = aFieldNames[itField]; + // note: get(..) returns a FieldID i.e. a int64_t + // while CellID (used previously) is a uint64_t + // similarly, the second argument of set(..) + // is signed (FieldID) rather than unsigned (CellID) + int id = aDecoder.get(cID,field); + if (aFieldCyclic[itField]) { + aDecoder[field].set(cID, cyclicNeighbour(id - 1, aFieldExtremes[itField])); + neighbours.emplace_back(cID); + aDecoder[field].set(cID, cyclicNeighbour(id + 1, aFieldExtremes[itField])); + neighbours.emplace_back(cID); + } else { + if (id > aFieldExtremes[itField].first) { + aDecoder[field].set(cID, id - 1); + neighbours.emplace_back(cID); + } + if (id < aFieldExtremes[itField].second) { + aDecoder[field].set(cID, id + 1); + neighbours.emplace_back(cID); + } + } + aDecoder[field].set(cID, id); + } + if (aDiagonal) { + std::vector fieldIds; // initial IDs + fieldIds.assign(aFieldNames.size(), 0); + // for each field get current Id + for (uint iField = 0; iField < aFieldNames.size(); iField++) { + const auto& field = aFieldNames[iField]; + fieldIds[iField] = aDecoder.get(cID, field); + } + for (uint iLength = aFieldNames.size(); iLength > 1; iLength--) { + // get all combinations for a given length + const auto& indexes = combinations(aFieldNames.size(), iLength); + for (uint iComb = 0; iComb < indexes.size(); iComb++) { + // for current combination get all permutations of +- 1 operation on IDs + const auto& calculation = permutations(iLength); + // do the increase/decrease of bitfield + for (uint iCalc = 0; iCalc < calculation.size(); iCalc++) { + // set new Ids for each field combination + bool add = true; + for (uint iField = 0; iField < indexes[iComb].size(); iField++) { + if (aFieldCyclic[indexes[iComb][iField]]) { + aDecoder[aFieldNames[indexes[iComb][iField]]].set(cID, cyclicNeighbour(fieldIds[indexes[iComb][iField]] + calculation[iCalc][iField], + aFieldExtremes[indexes[iComb][iField]]) ); + } else if ((calculation[iCalc][iField] > 0 && + fieldIds[indexes[iComb][iField]] < aFieldExtremes[indexes[iComb][iField]].second) || + (calculation[iCalc][iField] < 0 && + fieldIds[indexes[iComb][iField]] > aFieldExtremes[indexes[iComb][iField]].first)) { + aDecoder[aFieldNames[indexes[iComb][iField]]].set(cID, fieldIds[indexes[iComb][iField]] + calculation[iCalc][iField]); + } else { + add = false; + } + } + // add new cellId to neighbours (unless it's beyond extrema) + if (add) { + neighbours.emplace_back(cID); + } + // reset ids + for (uint iField = 0; iField < indexes[iComb].size(); iField++) { + aDecoder[aFieldNames[indexes[iComb][iField]]].set(cID, fieldIds[indexes[iComb][iField]]); + } + } + } + } + } + return neighbours; +} + +// use it for module-theta merged readout (FCCSWGridModuleThetaMerged_k4geo) +std::vector neighbours_ModuleThetaMerged(const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg, + const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, + const std::vector& aFieldNames, + const std::vector>& aFieldExtremes, + uint64_t aCellId, + bool aDiagonal) { + + std::vector neighbours; + + // check that field names and extremes have the proper length + if (aFieldNames.size() != 3 || aFieldExtremes.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 neighbours; + } + + // find index of layer, module and theta in field extremes 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 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 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 neighbours; + } + + // 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]); + + // now find the 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 + int neighbourTypeModuleDir; // 0: not neighbour; 1: diagonal neighbour; 2: neighbour in module direction + int neighbourTypeThetaDir; // 0: not neighbour; 1: diagonal neighbour; 2: neighbour in module direction + + for (int deltaLayer = -1; deltaLayer<2; deltaLayer+=2) { + + // no neighbours in layer N-1 for innermost layer + if (layer_id == aFieldExtremes[idLayerField].first && deltaLayer<0) continue; + // and in layer N+1 for outermost layer + if (layer_id == aFieldExtremes[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)); + if (theta_id_neighbour >= theta_id && theta_id_neighbour < (theta_id + aSeg.mergedThetaCells(layer_id))) neighbourTypeThetaDir = 2; + else if (theta_id_neighbour < theta_id && theta_id_neighbour > (theta_id - aSeg.mergedThetaCells(layer_id+deltaLayer))) neighbourTypeThetaDir = 2; + else if (theta_id_neighbour == (theta_id + aSeg.mergedThetaCells(layer_id))) neighbourTypeThetaDir = 1; + else if (theta_id_neighbour == (theta_id - aSeg.mergedThetaCells(layer_id+deltaLayer))) neighbourTypeThetaDir = 1; + else neighbourTypeThetaDir = 0; + + // if there is no point of contact along theta, no need to check also for module direction + if (neighbourTypeThetaDir == 0) continue; + // if we are not considering diagonal neighbours, and cells in theta have only an edge in common, then skip + if (!aDiagonal && neighbourTypeThetaDir == 1) continue; + // otherwise, check status along module direction + for (int j=-1; j <= aSeg.mergedModules(layer_id); j++) { + int module_id_neighbour = (module_id + j) - ((module_id + j) % aSeg.mergedModules(layer_id+deltaLayer)); + int module_id_neighbour_cyclic = cyclicNeighbour(module_id_neighbour, + aFieldExtremes[idModuleField] + ); + + if (module_id_neighbour >= module_id && module_id_neighbour < (module_id + aSeg.mergedModules(layer_id))) neighbourTypeModuleDir = 2; + else if (module_id_neighbour < module_id && module_id_neighbour > (module_id - aSeg.mergedModules(layer_id+deltaLayer))) neighbourTypeModuleDir = 2; + else if (module_id_neighbour == (module_id + aSeg.mergedModules(layer_id))) neighbourTypeModuleDir = 1; + else if (module_id_neighbour == (module_id - aSeg.mergedModules(layer_id+deltaLayer))) neighbourTypeModuleDir = 1; + else neighbourTypeModuleDir = 0; + + // if there is no point of contact along module, then skip + if (neighbourTypeModuleDir == 0) continue; + // otherwise: if neighbours along both module and theta, or along one of the two + // and we also consider diagonal neighbours, then add cells to list of neighbours + if ( (neighbourTypeModuleDir == 2 && neighbourTypeThetaDir==2) || + (aDiagonal && neighbourTypeThetaDir > 0 && neighbourTypeModuleDir>0) ) { + aDecoder.set(cID, aSeg.fieldNameModule(), module_id_neighbour_cyclic); + aDecoder.set(cID, aSeg.fieldNameTheta(), theta_id_neighbour); + neighbours.emplace_back(cID); + } + } + } + } + // reset cellID + // aDecoder.set(cID, aSeg.fieldNameModule(), module_id); + // aDecoder.set(cID, aSeg.fieldNameTheta(), theta_id); + + // for neighbours in module/theta direction at same layer_id, do +-nMergedCells instead of +-1 + aDecoder.set(cID, aSeg.fieldNameLayer(), layer_id); + // loop over theta cells + for (int i=-1; i<=1; i++) { + // calculate theta_id of neighbour + int theta_id_neighbour = theta_id + i*aSeg.mergedThetaCells(layer_id); + // check that it is within the ranges + if ( + (theta_id_neighbour < aFieldExtremes[idThetaField].first) || + (theta_id_neighbour > aFieldExtremes[idThetaField].second) + ) continue; + // set theta_id of cell ID + aDecoder[aSeg.fieldNameTheta()].set(cID, theta_id + i*aSeg.mergedThetaCells(layer_id)); + // loop over modules + for (int j=-1; j<=1; j++) { + // skip the cell under study (i==j==0) + if (i==0 && j==0) continue; + // calculate module_id of neighbour + int newid = cyclicNeighbour(module_id + j*aSeg.mergedModules(layer_id), aFieldExtremes[idModuleField]); + newid -= (newid % aSeg.mergedModules(layer_id)); + // set module_if of cell ID + aDecoder[aSeg.fieldNameModule()].set(cID, newid); + // add cell to neighbour list + if ( i==0 || j==0 || aDiagonal ) { // first two conditions correspond to non diagonal neighbours + neighbours.emplace_back(cID); + } + } + } + + // remove duplicates + std::unordered_set s; + for (uint64_t i : neighbours) + s.insert(i); + neighbours.assign( s.begin(), s.end() ); + return neighbours; +} + +std::vector> bitfieldExtremes(const dd4hep::DDSegmentation::BitFieldCoder& aDecoder, + const std::vector& aFieldNames) { + std::vector> extremes; + int width = 0; + for (const auto& field : aFieldNames) { + width = aDecoder[field].width(); + if (aDecoder[field].isSigned()) { + extremes.emplace_back(std::make_pair(-(1 << (width - 1)), (1 << (width - 1)) - 1)); + } else { + extremes.emplace_back(std::make_pair(0, (1 << width) - 1)); + } + } + return extremes; +} + +CLHEP::Hep3Vector envelopeDimensions(uint64_t aVolumeId) { + dd4hep::VolumeManager volMgr = dd4hep::Detector::getInstance().volumeManager(); + auto pvol = volMgr.lookupVolumePlacement(aVolumeId); + auto solid = pvol.volume().solid(); + // get the envelope of the shape + TGeoBBox* box = (dynamic_cast(solid.ptr())); + // get half-widths + return CLHEP::Hep3Vector(box->GetDX(), box->GetDY(), box->GetDZ()); +} + +std::array numberOfCells(uint64_t aVolumeId, const dd4hep::DDSegmentation::CartesianGridXY& aSeg) { + // // get half-widths + auto halfSizes = envelopeDimensions(aVolumeId); + // get segmentation cell widths + double xCellSize = aSeg.gridSizeX(); + double yCellSize = aSeg.gridSizeY(); + // calculate number of cells, the middle cell is centred at 0 (no offset) + uint cellsX = ceil((halfSizes.x() - xCellSize / 2.) / xCellSize) * 2 + 1; + uint cellsY = ceil((halfSizes.y() - yCellSize / 2.) / yCellSize) * 2 + 1; + return {cellsX, cellsY}; +} + +std::array numberOfCells(uint64_t aVolumeId, const dd4hep::DDSegmentation::CartesianGridXYZ& aSeg) { + // // get half-widths + auto halfSizes = envelopeDimensions(aVolumeId); + // get segmentation cell widths + double xCellSize = aSeg.gridSizeX(); + double yCellSize = aSeg.gridSizeY(); + double zCellSize = aSeg.gridSizeZ(); + // calculate number of cells, the middle cell is centred at 0 (no offset) + uint cellsX = ceil((halfSizes.x() - xCellSize / 2.) / xCellSize) * 2 + 1; + uint cellsY = ceil((halfSizes.y() - yCellSize / 2.) / yCellSize) * 2 + 1; + uint cellsZ = ceil((halfSizes.z() - zCellSize / 2.) / zCellSize) * 2 + 1; + return {cellsX, cellsY, cellsZ}; +} + +CLHEP::Hep3Vector tubeDimensions(uint64_t aVolumeId) { + dd4hep::VolumeManager volMgr = dd4hep::Detector::getInstance().volumeManager(); + auto pvol = volMgr.lookupVolumePlacement(aVolumeId); + auto solid = pvol.volume().solid(); + + // get the envelope of the shape + TGeoTubeSeg* tube = (dynamic_cast(solid.ptr())); + if (tube == nullptr) { + return CLHEP::Hep3Vector(0, 0, 0); + } + // get half-widths + return CLHEP::Hep3Vector(tube->GetRmin(), tube->GetRmax(), tube->GetDZ()); +} + +CLHEP::Hep3Vector coneDimensions(uint64_t aVolumeId) { + dd4hep::VolumeManager volMgr = dd4hep::Detector::getInstance().volumeManager(); + auto pvol = volMgr.lookupVolumePlacement(aVolumeId); + auto solid = pvol.volume().solid(); + // get the envelope of the shape + TGeoCone* cone = (dynamic_cast(solid.ptr())); + if (cone == nullptr) { + return CLHEP::Hep3Vector(0, 0, 0); + } + // get half-widths + return CLHEP::Hep3Vector(cone->GetRmin1(), cone->GetRmax1(), cone->GetDZ()); +} + +std::array tubeEtaExtremes(uint64_t aVolumeId) { + auto sizes = tubeDimensions(aVolumeId); + if (sizes.mag() == 0) { + // if it is not a cylinder maybe it is a cone (same calculation for extremes) + sizes = coneDimensions(aVolumeId); + if (sizes.mag() == 0) { + return {0, 0}; + } + } + // eta segmentation calculate maximum eta from the inner radius (no offset is taken into account) + double maxEta = 0; + double minEta = 0; + + double rIn = sizes.x(); + double rOut = sizes.y(); + double dZ = sizes.z(); + + // check if it is a cylinder centred at z=0 + dd4hep::VolumeManager volMgr = dd4hep::Detector::getInstance().volumeManager(); + auto detelement = volMgr.lookupDetElement(aVolumeId); + const auto& transformMatrix = detelement.nominal().worldTransformation(); + double outGlobal[3]; + double inLocal[] = {0, 0, 0}; // to get middle of the volume + transformMatrix.LocalToMaster(inLocal, outGlobal); + double zCenter = outGlobal[2]; + if (fabs(zCenter) < 1e-10) { + // this assumes cylinder centred at z=0 + maxEta = CLHEP::Hep3Vector(rIn, 0, dZ).eta(); + minEta = -maxEta; + } else { + maxEta = std::max( + CLHEP::Hep3Vector(rIn, 0, zCenter+dZ).eta(), + CLHEP::Hep3Vector(rOut, 0, zCenter+dZ).eta() + ); + minEta = std::min( + CLHEP::Hep3Vector(rIn, 0, zCenter-dZ).eta(), + CLHEP::Hep3Vector(rOut, 0, zCenter-dZ).eta() + ); + } + return {minEta, maxEta}; +} + +std::array envelopeEtaExtremes (uint64_t aVolumeId) { + dd4hep::VolumeManager volMgr = dd4hep::Detector::getInstance().volumeManager(); + auto detelement = volMgr.lookupDetElement(aVolumeId); + const auto& transformMatrix = detelement.nominal().worldTransformation(); + // calculate values of eta in all possible corners of the envelope + auto dim = envelopeDimensions(aVolumeId); + double minEta = 0; + double maxEta = 0; + for (uint i = 0; i < 8; i++) { + // coefficients to get all combinations of corners + int iX = -1 + 2 * ((i / 2) % 2); + int iY = -1 + 2 * (i % 2); + int iZ = -1 + 2 * (i / 4); + double outDimGlobal[3]; + double inDimLocal[] = {iX * dim.x(), iY * dim.y(), iZ * dim.z()}; + transformMatrix.LocalToMaster(inDimLocal, outDimGlobal); + double eta = CLHEP::Hep3Vector(outDimGlobal[0], outDimGlobal[1], outDimGlobal[2]).eta(); + if (i == 0) { + minEta = eta; + maxEta = eta; + } + if (eta < minEta) { + minEta = eta; + } + if (eta > maxEta) { + maxEta = eta; + } + } + return {minEta, maxEta}; +} + +std::array volumeEtaExtremes(uint64_t aVolumeId) { + // try if volume is a cylinder/disc + auto etaExtremes = tubeEtaExtremes(aVolumeId); + if (etaExtremes[0] != 0 or etaExtremes[1] != 0) { + return etaExtremes; + } else { + return envelopeEtaExtremes(aVolumeId); + } +} + +std::array numberOfCells(uint64_t aVolumeId, const dd4hep::DDSegmentation::FCCSWGridPhiEta_k4geo& aSeg) { + // get segmentation number of bins in phi + uint phiCellNumber = aSeg.phiBins(); + // get segmentation cell width in eta + double etaCellSize = aSeg.gridSizeEta(); + // get min and max eta of the volume + auto etaExtremes = volumeEtaExtremes(aVolumeId); + // calculate the number of eta volumes + // max - min = full eta range, - size = not counting the middle cell centred at 0, + 1 to account for that cell + uint cellsEta = ceil(( etaExtremes[1] - etaExtremes[0] - etaCellSize ) / 2 / etaCellSize) * 2 + 1; + uint minEtaID = int(floor((etaExtremes[0] + 0.5 * etaCellSize - aSeg.offsetEta()) / etaCellSize)); + return {phiCellNumber, cellsEta, minEtaID}; +} + +std::array numberOfCells(uint64_t aVolumeId, const dd4hep::DDSegmentation::FCCSWGridPhiTheta_k4geo& aSeg) { + uint phiCellNumber = aSeg.phiBins(); + double thetaCellSize = aSeg.gridSizeTheta(); + double thetaOffset = aSeg.offsetTheta(); + auto etaExtremes = volumeEtaExtremes(aVolumeId); + double thetaMin = 2.*atan(exp(-etaExtremes[1])); + double thetaMax = 2.*atan(exp(-etaExtremes[0])); + // debug + std::cout << "volumeID = " << aVolumeId << std::endl; + std::cout << "thetaMin, thetaMax = " << thetaMin << " " << thetaMax << std::endl; + // + uint minThetaID = int(floor((thetaMin + 0.5 * thetaCellSize - thetaOffset) / thetaCellSize)); + uint maxThetaID = int(floor((thetaMax + 0.5 * thetaCellSize - thetaOffset) / thetaCellSize)); + uint nThetaCells = 1 + maxThetaID - minThetaID; + return {phiCellNumber, nThetaCells, minThetaID}; +} + +std::array numberOfCells(uint64_t aVolumeId, const dd4hep::DDSegmentation::FCCSWGridModuleThetaMerged_k4geo& aSeg) { + + const dd4hep::DDSegmentation::BitFieldCoder* aDecoder = aSeg.decoder(); + int nLayer = aDecoder->get(aVolumeId, aSeg.fieldNameLayer()); + // + 0.5 to avoid integer division + uint nModules = aSeg.nModules() / aSeg.mergedModules(nLayer); + if (aSeg.nModules() % aSeg.mergedModules(nLayer) != 0) nModules++; + // get minimum and maximum theta of volume + auto etaExtremes = volumeEtaExtremes(aVolumeId); + double thetaMin = 2.*atan(exp(-etaExtremes[1])); + double thetaMax = 2.*atan(exp(-etaExtremes[0])); + + // convert to minimum and maximum theta bins + double thetaCellSize = aSeg.gridSizeTheta(); + double thetaOffset = aSeg.offsetTheta(); + uint minThetaID = int(floor((thetaMin + 0.5 * thetaCellSize - thetaOffset) / thetaCellSize)); + uint maxThetaID = int(floor((thetaMax + 0.5 * thetaCellSize - thetaOffset) / thetaCellSize)); + // correct minThetaID and maxThetaID for merging + uint mergedThetaCells = aSeg.mergedThetaCells(nLayer); + minThetaID -= (minThetaID % mergedThetaCells); + maxThetaID -= (maxThetaID % mergedThetaCells); + uint nThetaCells = 1 + (maxThetaID - minThetaID)/ mergedThetaCells; + return {nModules, nThetaCells, minThetaID}; +} + +std::array numberOfCells(uint64_t aVolumeId, const dd4hep::DDSegmentation::PolarGridRPhi& aSeg) { + // get half-widths, + auto tubeSizes = tubeDimensions(aVolumeId); + // get segmentation cell width + double rCellSize = aSeg.gridSizeR(); + double phiCellSize = aSeg.gridSizePhi(); + uint cellsRout = ceil(tubeSizes.y() / rCellSize); + uint cellsRin = floor(tubeSizes.x() / rCellSize); + uint cellsR = cellsRout - cellsRin; + uint cellsPhi = ceil(2 * M_PI / phiCellSize); + return {cellsR, cellsPhi}; +} + +unsigned int countPlacedVolumes(TGeoVolume* aHighestVolume, const std::string& aMatchName) { + int numberOfPlacedVolumes = 0; + TGeoNode* node; + TGeoIterator next(aHighestVolume); + while ((node = next())) { + std::string currentNodeName = node->GetName(); + if (currentNodeName.find(aMatchName) != std::string::npos) { + ++numberOfPlacedVolumes; + } + } + return numberOfPlacedVolumes; +} +} +} From fa7796bb47982df02f4083b3b84ae7da832a2050 Mon Sep 17 00:00:00 2001 From: Giovanni Marchiori Date: Mon, 11 Dec 2023 12:34:14 +0100 Subject: [PATCH 08/29] implement suggestions by Andre Pleier --- detectorCommon/CMakeLists.txt | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/detectorCommon/CMakeLists.txt b/detectorCommon/CMakeLists.txt index 4bc3abc9d..0982e0a4c 100644 --- a/detectorCommon/CMakeLists.txt +++ b/detectorCommon/CMakeLists.txt @@ -3,11 +3,11 @@ ################################################################################ file(GLOB sources src/*.cpp) -add_library(detectorCommon SHARED ${sources}) +add_dd4hep_plugin(detectorCommon SHARED ${sources}) target_link_libraries(detectorCommon DD4hep::DDCore DD4hep::DDG4 detectorSegmentations) target_include_directories(detectorCommon PUBLIC - $ + $ $ ) @@ -18,13 +18,4 @@ install(TARGETS detectorCommon EXPORT ${PROJECT_NAME}Targets RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT bin LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT shlib - PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_PREFIX}/include/detectorCommon" - COMPONENT dev) - - -dd4hep_generate_rootmap(detectorCommon) - -#include(CTest) -#gaudi_add_test(DumpSimpleBox -# WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} -# FRAMEWORK tests/dumpSimpleBox.py) + PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/detectorCommon" COMPONENT dev) From 843eae8485646bb256010df84158c4ab06634f4e Mon Sep 17 00:00:00 2001 From: BrieucF Date: Mon, 13 Nov 2023 13:51:17 +0100 Subject: [PATCH 09/29] [IDEA] Add detailed drift chamber from FCCDetectors --- .../DectDimensions_IDEA_o1_v01.xml | 4 +- .../IDEA_o1_v02/DriftChamber_o1_v01.xml | 98 ++ .../IDEA/compact/IDEA_o1_v02/IDEA_o1_v02.xml | 9 +- .../compact/IDEA_o1_v02/materials_o1_v01.xml | 121 ++- FCCee/IDEA/compact/README.md | 1 + detector/tracker/DriftChamber_o1_v01.cpp | 924 ++++++++++++++++++ detector/tracker/README.md | 17 +- 7 files changed, 1159 insertions(+), 15 deletions(-) create mode 100644 FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml create mode 100644 detector/tracker/DriftChamber_o1_v01.cpp 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 8226c97f4..8211dbdf2 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 @@ -89,8 +89,8 @@ - - + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml new file mode 100644 index 000000000..f70ad90a0 --- /dev/null +++ b/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml @@ -0,0 +1,98 @@ + + + + Detector description for the IDEA Drift Chamber + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + system:4,superLayer:5,layer:5,phi:11,hitorigin:3,stereo:1,layerInCell:2 + + + + + + + + + + + + + + + + + + + + + + + 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 b6dea340e..210d253f6 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v02/IDEA_o1_v02.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v02/IDEA_o1_v02.xml @@ -33,13 +33,16 @@ - + - + Import vertex + --> + + + diff --git a/FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml index 878cddd00..f68afa8b4 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml @@ -299,14 +299,6 @@ - - - - - - - -

@@ -354,4 +346,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FCCee/IDEA/compact/README.md b/FCCee/IDEA/compact/README.md index b088aec4c..532f3335f 100644 --- a/FCCee/IDEA/compact/README.md +++ b/FCCee/IDEA/compact/README.md @@ -1,3 +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 diff --git a/detector/tracker/DriftChamber_o1_v01.cpp b/detector/tracker/DriftChamber_o1_v01.cpp new file mode 100644 index 000000000..a61b49163 --- /dev/null +++ b/detector/tracker/DriftChamber_o1_v01.cpp @@ -0,0 +1,924 @@ +/***************************************************************************************\ +* DD4hep geometry code for the central drift chamber of the IDEA detector * +* Author: Lorenzo Capriotti, Modified by Brieuc Francois to have sensitive cell volumes * +\***************************************************************************************/ +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/Printout.h" +#include "DD4hep/detail/DetectorInterna.h" +#include "TClass.h" +#include "TMath.h" +#include "XML/Utilities.h" +#include +#include +#include + +using namespace std; +using namespace dd4hep; + +struct wire +{ + dd4hep::Volume mother_volume; + string type; + int num; + double radius; + double phi; + double phioffset; + double stereo; + double thickness; + double halflength; + dd4hep::Volume volume; + string name; +}; + +namespace { + +struct CDCHBuild : public dd4hep::xml::tools::VolumeBuilder { + std::vector deSuperLayer, deLayer, deSWire; + + CDCHBuild(dd4hep::Detector& description, xml_elt_t e, dd4hep::SensitiveDetector sens); + + double diff_of_squares(double a, double b); + void apply_wire_coating(struct wire& w, double outwrap, double halflength, string material); + void PlaceWires(struct wire& w, double outwrap, double halflength, int SL, int ilayer); + void build_layer(DetElement parent, Volume parentVol, dd4hep::SensitiveDetector sens); +}; + +// ****************************************************** +// Initializing constructor +// ****************************************************** + +CDCHBuild::CDCHBuild(dd4hep::Detector& dsc, xml_elt_t e, dd4hep::SensitiveDetector sens) + : dd4hep::xml::tools::VolumeBuilder(dsc, e, sens) {} + +double CDCHBuild::diff_of_squares(double a, double b) { + + double diff = pow(a, 2) - pow(b, 2); + return diff; +} + +void CDCHBuild::apply_wire_coating(struct wire& w, double outwrap, double halflength, string material = "Silver"){ + dd4hep::Tube WrapTube(w.thickness, w.thickness + 0.5 * outwrap, halflength); + dd4hep::Volume WireWrapVol(w.name + "_coating", WrapTube, description.material(material)); + dd4hep::Tube TotalWire(0.0, w.thickness + 0.5 * outwrap, halflength); + dd4hep::Volume WireVol(w.name + "_totalWire", TotalWire, description.material("Air")); + WireVol.placeVolume(w.volume, dd4hep::Position(0.0, 0.0, 0.0)); + WireVol.placeVolume(WireWrapVol, dd4hep::Position(0.0, 0.0, 0.0)); + w.volume = WireVol; +} + +// deprecated function, only use it for the wires before and after the sensitive zone (mainly guard wires) +void CDCHBuild::PlaceWires(struct wire& w, double outwrap, double halflength, int SL = 999, + int ilayer = 999) { + + dd4hep::RotationZYX rot(0., 0., w.stereo); + dd4hep::RotationX rot_stereo(w.stereo); + dd4hep::Translation3D transl(w.radius, 0., 0.); + + dd4hep::Transform3D T(transl * rot_stereo); + + string wirewrapname = "WireWrap_SL"; + wirewrapname += std::to_string(SL); + wirewrapname += "_layer"; + wirewrapname += std::to_string(ilayer); + wirewrapname += "_type"; + wirewrapname += w.type; + wirewrapname += "_stereo"; + wirewrapname += std::to_string(w.stereo); + + //cout << "wirewrapname: " << wirewrapname << endl; + + string wirename = "Wire_SL"; + wirename += std::to_string(SL); + wirename += "_layer"; + wirename += std::to_string(ilayer); + wirename += "_type"; + wirename += w.type; + wirename += "_stereo"; + wirename += std::to_string(w.stereo); + + apply_wire_coating(w, outwrap, halflength); + + // registerVolume(WireWrapVol.name(), WireWrapVol); + // registerVolume(WireVol.name(), WireVol); + + // repeat the placement of wires over phi + for (int n = 0; n < w.num; n++) { + dd4hep::RotationZ iRot(w.phioffset + w.phi * n); + if (n % 1 == 0) w.mother_volume.placeVolume(w.volume, dd4hep::Transform3D(iRot * T)); + } +} + +void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::SensitiveDetector sens_det) { + + // ****************************************************** + // Loading parameters + // ****************************************************** + + double halfalpha = 0.5 * dd4hep::_toDouble("CDCH:alpha"); + double inner_radius = dd4hep::_toDouble("CDCH:r0"); + double outer_radius = dd4hep::_toDouble("CDCH:rOut"); + double zHalfExtentWithServices = dd4hep::_toDouble("CDCH:zHalfExtentWithServices"); + double CarbonInnerWallThick = dd4hep::_toDouble("CDCH:CarbonInnerWallThick"); + double CopperInnerWallThick = dd4hep::_toDouble("CDCH:CopperInnerWallThick"); + double GasInnerWallThick = dd4hep::_toDouble("CDCH:GasInnerWallThick"); + double Carbon1OuterWallThick = dd4hep::_toDouble("CDCH:Carbon1OuterWallThick"); + double Carbon2OuterWallThick = dd4hep::_toDouble("CDCH:Carbon2OuterWallThick"); + double CopperOuterWallThick = dd4hep::_toDouble("CDCH:CopperOuterWallThick"); + double FoamOuterWallThick = dd4hep::_toDouble("CDCH:FoamOuterWallThick"); + double GasEndcapWallThick = dd4hep::_toDouble("CDCH:GasEndcapWallThick"); + double CopperEndcapWallThick = dd4hep::_toDouble("CDCH:CopperEndcapWallThick"); + double KaptonEndcapWallThick = dd4hep::_toDouble("CDCH:KaptonEndcapWallThick"); + double CarbonEndcapWallThick = dd4hep::_toDouble("CDCH:CarbonEndcapWallThick"); + double FWireShellThickIn = dd4hep::_toDouble("CDCH:FWireShellThickIn"); + double FWireShellThickOut = dd4hep::_toDouble("CDCH:FWireShellThickOut"); + double centerFWireShellThickIn = dd4hep::_toDouble("CDCH:centerFWireShellThickIn"); + double centerFWireShellThickOut = dd4hep::_toDouble("CDCH:centerFWireShellThickOut"); + double SWireShellThickIn = dd4hep::_toDouble("CDCH:SWireShellThickIn"); + double SWireShellThickOut = dd4hep::_toDouble("CDCH:SWireShellThickOut"); + double InGWireShellThickIn = dd4hep::_toDouble("CDCH:InGWireShellThickIn"); + double InGWireShellThickOut = dd4hep::_toDouble("CDCH:InGWireShellThickOut"); + double OutGWireShellThickIn = dd4hep::_toDouble("CDCH:InGWireShellThickIn"); + double OutGWireShellThickOut = dd4hep::_toDouble("CDCH:InGWireShellThickOut"); + double secure = dd4hep::_toDouble("CDCH:secure"); + double capGasLayer = dd4hep::_toDouble("CDCH:capGasLayer"); + double extShiftFW = dd4hep::_toDouble("CDCH:extShiftFW"); + double cellDimension = dd4hep::_toDouble("CDCH:cellDimension"); + double inGuardRad = dd4hep::_toDouble("CDCH:inGuardRad"); + double outGuardRad = dd4hep::_toDouble("CDCH:outGuardRad"); + int nSDeltaWire = dd4hep::_toInt("CDCH:nSDeltaWire"); + int nSWire = dd4hep::_toInt("CDCH:nSWire"); + int nStoFWireRatio = dd4hep::_toInt("CDCH:nStoFWireRatio"); + int nVerticalFWire = dd4hep::_toInt("CDCH:nVerticalFWire"); + int nSuperLayer = dd4hep::_toInt("CDCH:nSuperLayer"); + int nLayer = dd4hep::_toInt("CDCH:nLayer"); + int nFieldWireShells = dd4hep::_toInt("CDCH:nFieldWireShells"); + //bool setWireSensitive = true; // FIXME: add the possibility to have wires sensitive (parameter in the xml) which could be useful for detailed chamber behavior studies, current attempt never lead to a hit in the wire, even with enlarged wires... + double halflength = zHalfExtentWithServices - (GasEndcapWallThick + CopperEndcapWallThick + KaptonEndcapWallThick + CarbonEndcapWallThick); // this will be the sensitive volume z extent + + double epsilon = 0.0; + double phi_layer = 0.0; + double phi_layer1 = 0.0; + int nFWire = 0; + int nFWire1 = 0; + int num_wire = 0; + int nHorizontalFWire = nStoFWireRatio - nVerticalFWire; + int sign_epsilon = -1; + double phi = 0.0; + double scaleFactor = 0.0; + double dropFactor = 0.0; + double epsilonFactor = 0.0; + double delta_radius_layer = cellDimension; + double senseWireRing_radius_0 = 0.0; + double iradius = 0.0; + double idelta_radius = 0.0; + + double envelop_Inner_thickness = CarbonInnerWallThick + CopperInnerWallThick + GasInnerWallThick; + double envelop_Outer_thickness = + Carbon1OuterWallThick + Carbon2OuterWallThick + CopperOuterWallThick + FoamOuterWallThick; + double FWireDiameter = FWireShellThickIn + FWireShellThickOut; + double FWradii = 0.5 * FWireDiameter; + double SWireDiameter = SWireShellThickIn + SWireShellThickOut; + double SWradii = 0.5 * SWireDiameter; + double inGWireDiameter = InGWireShellThickIn + InGWireShellThickOut; + double inGWradii = 0.5 * inGWireDiameter; + double fakeLayerInIWthick = -0.0001 + GasInnerWallThick; + double inner_radius_0 = inner_radius + envelop_Inner_thickness - fakeLayerInIWthick; + + double radius_layer_0 = inner_radius + envelop_Inner_thickness + FWradii + secure + capGasLayer; + double radius_layerOut_0 = radius_layer_0 - FWradii - secure; + + double drop = 0.0; + double radius_layer = 0.0; + double radius_layerIn_0 = 0.0; + double radius_layerIn = 0.0; + double radius_layerOut = 0.0; + double epsilonIn = 0.0; + double epsilonOut = 0.0; + double layerangle = 0.0; + double cellBase = 0.0; + double inscribedRadius = 0.0; + double circumscribedRadius = 0.0; + double zlength = 0.0; + double cellStaggering = 0.0; + double epsilonInGwRing = 0.0; + double epsilonOutGwRing = 0.0; + double radius_layerIn_whole_cell = 0.0; + double epsilonIn_whole_cell = 0.0; + + //------------------------------------------------------------------------ + // The enlarge parameter is used to see the wires in the rendering + //------------------------------------------------------------------------ + + double enlarge = 50.; + + //------------------------------------------------------------------------ + // Build the inner, outer and endcap walls first + //------------------------------------------------------------------------ + + dd4hep::Tube Endcap_Gas(inner_radius, outer_radius, 0.5 * GasEndcapWallThick); + dd4hep::Tube Endcap_Copper(inner_radius, outer_radius, 0.5 * CopperEndcapWallThick); + dd4hep::Tube Endcap_Kapton(inner_radius, outer_radius, 0.5 * KaptonEndcapWallThick); + dd4hep::Tube Endcap_Carbon(inner_radius, outer_radius, 0.5 * CarbonEndcapWallThick); + + dd4hep::Volume lvEndcapWallGas = + dd4hep::Volume("lvEndcapWallGasVol", Endcap_Gas, description.material("GasHe_90Isob_10")); + dd4hep::Volume lvEndcapWallCopper = + dd4hep::Volume("lvEndcapWallCopperVol", Endcap_Copper, description.material("G4_Cu")); + dd4hep::Volume lvEndcapWallKapton = + dd4hep::Volume("lvEndcapWallKaptonVol", Endcap_Kapton, description.material("Kapton")); + dd4hep::Volume lvEndcapWallCarbon = + dd4hep::Volume("lvEndcapWallCarbonVol", Endcap_Carbon, description.material("CarbonFiber")); + + dd4hep::Tube InnerWall_Carbon(inner_radius, inner_radius + CarbonInnerWallThick, halflength); + dd4hep::Tube InnerWall_Copper(inner_radius + CarbonInnerWallThick, + inner_radius + CarbonInnerWallThick + CopperInnerWallThick, halflength); + dd4hep::Tube InnerWall_Gas(inner_radius + CarbonInnerWallThick + CopperInnerWallThick, + inner_radius + envelop_Inner_thickness, halflength); + + dd4hep::Volume lvInnerWallCarbon = + dd4hep::Volume("lvInnerWallCarbonVol", InnerWall_Carbon, description.material("CarbonFiber")); + dd4hep::Volume lvInnerWallCopper = + dd4hep::Volume("lvInnerWallCopperVol", InnerWall_Copper, description.material("G4_Cu")); + dd4hep::Volume lvInnerWallGas = + dd4hep::Volume("lvInnerWallGasVol", InnerWall_Gas, description.material("GasHe_90Isob_10")); + + dd4hep::Tube OuterWall_Copper(outer_radius - envelop_Outer_thickness, + outer_radius - Carbon1OuterWallThick - Carbon2OuterWallThick - FoamOuterWallThick, + halflength); + dd4hep::Tube OuterWall_Carbon1(outer_radius - Carbon1OuterWallThick - Carbon2OuterWallThick - FoamOuterWallThick, + outer_radius - Carbon2OuterWallThick - FoamOuterWallThick, halflength);// FIXME there is an overlap with OuterWall_Carbon1 and the last guard wire layer + dd4hep::Tube OuterWall_Foam(outer_radius - Carbon2OuterWallThick - FoamOuterWallThick, + outer_radius - Carbon2OuterWallThick, halflength); + dd4hep::Tube OuterWall_Carbon2(outer_radius - Carbon2OuterWallThick, outer_radius, halflength); + + dd4hep::Volume lvOuterWallCarbon1 = + dd4hep::Volume("lvOuterWallCarbon1Vol", OuterWall_Carbon1, description.material("CarbonFiber")); + dd4hep::Volume lvOuterWallCarbon2 = + dd4hep::Volume("lvOuterWallCarbon2Vol", OuterWall_Carbon2, description.material("CarbonFiber")); + dd4hep::Volume lvOuterWallCopper = + dd4hep::Volume("lvOuterWallCopperVol", OuterWall_Copper, description.material("G4_Cu")); + dd4hep::Volume lvOuterWallFoam = + dd4hep::Volume("lvOuterWallFoamVol", OuterWall_Foam, description.material("GasHe_90Isob_10")); + + + //------------------------------------------------------------------------ + // Now we are ready to loop over the SuperLayers and fill the gas volume! + //------------------------------------------------------------------------ + + std::vector lvLayerVol; + std::vector lvFwireVol, lvGwireVol; + + string wirecol, gascol, wholeHyperboloidVolumeName; + string lvFwireName, lvSwireName; + + struct wire guard_wires{}, field_wires_bottom{}, field_wires_center{}, field_wires_top{}, sense_wires{}; + // nSuperLayer = 1; + + for (int SL = 0; SL < nSuperLayer; ++SL) { + + num_wire = nSWire + SL * nSDeltaWire; + phi = 2. * TMath::Pi() / num_wire; + nFWire = nHorizontalFWire * num_wire; + phi_layer = 2. * TMath::Pi() / nFWire; + nFWire1 = nFWire / 2; + if (ceilf(nFWire1) != nFWire1) + throw std::runtime_error("Error: Failed to build CDCH. Please make sure that '(nStoFWireRatio - nVerticalFWire) * (nSWire + SuperLayerIndex * nSDeltaWire)' is always an even number"); + phi_layer1 = 2.0 * phi_layer; + scaleFactor = (1.0 + TMath::Pi() / num_wire) / (1.0 - TMath::Pi() / num_wire); + dropFactor = (1.0 / cos(halfalpha) - 1.0); // used to determine the radius of the hyperboloid in z = +- halflength with r_out = r_min + r_min * dropFactor + epsilonFactor = sin(halfalpha) / halflength; + layerangle = -0.5 * phi; + + gascol = "vCDCH:Gas1"; + if (SL % 3 == 0) + gascol = "vCDCH:Gas1"; + else if ((SL + 1) % 3 == 0) + gascol = "vCDCH:Gas2"; + else if ((SL + 2) % 3 == 0) + gascol = "vCDCH:Gas3"; + + if (SL % 3 == 0) + wirecol = "vCDCH:Wire1"; + else if ((SL + 1) % 3 == 0) + wirecol = "vCDCH:Wire2"; + else if ((SL + 2) % 3 == 0) + wirecol = "vCDCH:Wire3"; + + if (SL == 0) {// SL = 0 is special due to the guard wires and the first field wires that lie outside of the sensitive volume + double stereoOut0 = atan(sqrt(diff_of_squares((inGuardRad - inGWradii) + (inGuardRad - inGWradii) * dropFactor, inGuardRad - inGWradii)) / halflength); + + dd4hep::Hyperboloid HypeLayer0(inner_radius_0, 0.0, radius_layerOut_0 - secure, stereoOut0, halflength); + lvLayerVol.push_back(dd4hep::Volume("hyperboloid_inner_guard_layer", HypeLayer0, description.material("GasHe_90Isob_10"))); + lvLayerVol.back().setVisAttributes(description, "vCDCH:Pb"); + + epsilonInGwRing = atan(inGuardRad * (1.0 + dropFactor) * epsilonFactor); + zlength = halflength; + zlength -= sin(epsilonInGwRing) * inGWradii; + zlength /= cos(epsilonInGwRing); + + guard_wires.mother_volume = lvLayerVol.back(); + guard_wires.type = "G"; + guard_wires.num = nFWire1; //(#guard wires == # field wires) + guard_wires.radius = inGuardRad - inGWradii; + guard_wires.phi = 2. * TMath::Pi() / guard_wires.num; + guard_wires.phioffset = layerangle; + guard_wires.stereo = epsilonInGwRing; + guard_wires.thickness = 0.5 * InGWireShellThickIn * enlarge; // half the inner thickness as radius of tube + guard_wires.halflength = zlength; + guard_wires.name = string("Gwire_inner_stereoplus"); + + dd4hep::Tube Gwire(0.0, guard_wires.thickness, halflength); + lvGwireVol.push_back(dd4hep::Volume("Gwire_inner", Gwire, description.material("G4_Al"))); + lvGwireVol.back().setVisAttributes(description, wirecol); + + guard_wires.volume = lvGwireVol.back(); + CDCHBuild::PlaceWires(guard_wires, FWireShellThickOut, halflength, SL, -1); + + guard_wires.volume = lvGwireVol.back(); // needed because applyWireCoating acts on it + guard_wires.radius = inGuardRad + inGWradii + extShiftFW; + guard_wires.phioffset = layerangle + phi_layer; + guard_wires.stereo = -1.0 * epsilonInGwRing; + guard_wires.name = string("Gwire_inner_stereominus"); + CDCHBuild::PlaceWires(guard_wires, FWireShellThickOut, halflength, SL, -1); + + drop = radius_layer_0 * dropFactor; + radius_layer = radius_layer_0 + drop; + epsilon = atan(radius_layer * epsilonFactor); + radius_layerIn_0 = radius_layer_0 - FWradii - 2.0 * secure; + radius_layerIn = radius_layerIn_0 + drop; + radius_layerOut_0 = radius_layer_0 + FWradii; + radius_layerOut = radius_layerOut_0 + drop; + epsilonIn = atan(sqrt(pow(radius_layerIn, 2) - pow(radius_layerIn_0, 2)) / halflength); + epsilonOut = atan(sqrt(pow(radius_layerOut, 2) - pow(radius_layerOut_0, 2)) / halflength); + + dd4hep::Hyperboloid HypeLayer1(radius_layerIn_0, epsilonIn, radius_layerOut_0, epsilonOut, halflength); + lvLayerVol.push_back(dd4hep::Volume("hyperboloid_first_field_wire_ring", HypeLayer1, description.material("GasHe_90Isob_10"))); + lvLayerVol.back().setVisAttributes(description, "vCDCH:Plastic"); + + zlength = halflength; + zlength -= sin(epsilon) * FWradii; + zlength /= cos(epsilon); + + field_wires_top.mother_volume = lvLayerVol.back(); + field_wires_top.type = "F"; + field_wires_top.num = nFWire1; + field_wires_top.radius = radius_layerIn_0 - FWradii - extShiftFW; + field_wires_top.phi = 2. * TMath::Pi() /field_wires_top.num;; + field_wires_top.phioffset = layerangle + cellStaggering - phi_layer; + field_wires_top.stereo = sign_epsilon * epsilon; + field_wires_top.thickness = 0.5 * FWireShellThickIn * enlarge; + field_wires_top.halflength = zlength; + + lvFwireName = dd4hep::_toString(SL, "lvFwire_%d_init"); + field_wires_top.name = string(lvFwireName); + + dd4hep::Tube Fwire(0.0, field_wires_top.thickness, halflength); + lvFwireVol.push_back(dd4hep::Volume(lvFwireName, Fwire, description.material("G4_Al"))); + lvFwireVol.back().setVisAttributes(description, wirecol); + + field_wires_top.volume = lvFwireVol.back(); + CDCHBuild::PlaceWires(field_wires_top, FWireShellThickOut, halflength, SL, -1); + + radius_layer_0 += FWradii; + + + // the commented part below is a trial to get totally rid of PlaceWire function and to treat wires outside of the sensitive volume the same way as the one inside + + //// deal with the first guard layer + //double stereoOut0 = atan((radius_layerOut_0 + FWradii) * (1.0 * dropFactor * epsilonFactor)); + ////stereoOut0 = atan(sqrt(diff_of_squares(radius_layerOut_0 + FWradii, + + ////radius_layerOut_0 = radius_layerIn_0 + FWireDiameter + 2.0 * secure; + ////radius_layerOut = radius_layerOut_0 + drop; + ////epsilonOut = atan(sqrt(diff_of_squares(radius_layerOut, radius_layerOut_0)) / halflength); + ////dd4hep::Hyperboloid HypeLayer0(inner_radius_0, 0.0, radius_layerOut_0 + FWradii - secure, stereoOut0, halflength); + //dd4hep::Hyperboloid HypeLayer0(inner_radius_0, 0.0, radius_layerOut_0 + FWradii, stereoOut0, halflength); + //dd4hep::Volume inner_guard_layer_volume("hyperboloid_inner_guard_layer", HypeLayer0, description.material("GasHe_90Isob_10")); + //dd4hep::PlacedVolume inner_guard_layer_placedVolume = parentVol.placeVolume(inner_guard_layer_volume); + //CDCHDetector.setPlacement(inner_guard_layer_placedVolume); + + //epsilonInGwRing = atan(inGuardRad * (1.0 + dropFactor) * epsilonFactor); + //zlength = halflength; + //zlength -= sin(epsilonInGwRing) * inGWradii; + //zlength /= cos(epsilonInGwRing); + + //guard_wires.mother_volume = inner_guard_layer_volume; + //guard_wires.type = "G"; + //guard_wires.num = nInGWire; + //guard_wires.radius = inGuardRad - inGWradii; + //guard_wires.phi = 2. * TMath::Pi() / guard_wires.num; + //guard_wires.phioffset = layerangle; + //guard_wires.stereo = epsilonInGwRing; + //guard_wires.thickness = 0.5 * InGWireShellThickIn * enlarge; // half the inner thickness as radius of tube + //guard_wires.halflength = zlength; + //guard_wires.name = string("InnerGuardWire") + dd4hep::_toString(guard_wires.stereo, "_stereo%f"); + //dd4hep::Tube Gwire(0.0, guard_wires.thickness, halflength); + //guard_wires.volume = dd4hep::Volume("InnerGuardWire", Gwire, description.material("G4_Al")); + //apply_wire_coating(guard_wires, InGWireShellThickIn, halflength); + //// Radial translation + //dd4hep::Translation3D radial_translation_guard_wire(guard_wires.radius, 0., 0.); + //// stereo rotation + //dd4hep::RotationX rot_stereo_guard_wire(guard_wires.stereo); + //dd4hep::PlacedVolume inner_guard_wire_placedvolume; + //for (int phi_index = 0; phi_index < guard_wires.num; phi_index++) { + // dd4hep::RotationZ iRot(guard_wires.phioffset + guard_wires.phi * phi_index); + // dd4hep::Transform3D total_transformation(iRot * radial_translation_guard_wire * rot_stereo_guard_wire); + // inner_guard_wire_placedvolume = inner_guard_layer_volume.placeVolume(guard_wires.volume, total_transformation); + // //if(setWireSensitive) + // // inner_guard_wire_placedvolume.addPhysVolID("phi", phi_index).addPhysVolID("hitorigin", 3).addPhysVolID("stereo", guard_wires.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 0); + //} + + //guard_wires.radius = inGuardRad + inGWradii + extShiftFW; + //guard_wires.phioffset = layerangle + phi_layer; + //guard_wires.stereo = -1.0 * epsilonInGwRing; + //guard_wires.name = string("InnerGuardWire") + dd4hep::_toString(guard_wires.stereo, "_stereo%f"); + + //drop = radius_layer_0 * dropFactor; + //radius_layer = radius_layer_0 + drop; + //epsilon = atan(radius_layer * epsilonFactor); + //radius_layerIn_0 = radius_layer_0 - FWradii - 2.0 * secure; + //radius_layerIn = radius_layerIn_0 + drop; + //radius_layerOut_0 = radius_layer_0 + FWradii; + //radius_layerOut = radius_layerOut_0 + drop; + //epsilonIn = atan(sqrt(pow(radius_layerIn, 2) - pow(radius_layerIn_0, 2)) / halflength); + //epsilonOut = atan(sqrt(pow(radius_layerOut, 2) - pow(radius_layerOut_0, 2)) / halflength); + + //dd4hep::Hyperboloid HypeLayer1(radius_layerIn_0, epsilonIn, radius_layerOut_0, epsilonOut, halflength); + //lvLayerVol.push_back(dd4hep::Volume("lvLayer_0", HypeLayer1, description.material("GasHe_90Isob_10"))); + //lvLayerVol.back().setVisAttributes(description, "vCDCH:Plastic"); + + //zlength = halflength; + //zlength -= sin(epsilon) * FWradii; + //zlength /= cos(epsilon); + + //field_wires_top.mother_volume = lvLayerVol.back(); + //field_wires_top.type = "F"; + //field_wires_top.num = nFWire1; + //field_wires_top.radius = radius_layerIn_0 - FWradii - extShiftFW; + //field_wires_top.phi = phi_layer1; + //field_wires_top.phioffset = layerangle + cellStaggering - phi_layer; + //field_wires_top.stereo = sign_epsilon * epsilon; + //field_wires_top.thickness = 0.5 * FWireShellThickIn * enlarge; + //field_wires_top.halflength = zlength; + //field_wires_top.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(-1, "_layer%d") + string("_type") + field_wires_top.type + dd4hep::_toString(field_wires_top.stereo, "_stereo%f_top"); + + //lvFwireName = dd4hep::_toString(SL, "lvFwire_%d_init"); + + //dd4hep::Tube Fwire(0.0, field_wires_top.thickness, halflength); + //lvFwireVol.push_back(dd4hep::Volume(lvFwireName, Fwire, description.material("G4_Al"))); + //lvFwireVol.back().setVisAttributes(description, wirecol); + + ////field_wires_top.volume = lvFwireVol.back(); + //////CDCHBuild::PlaceWires(field_wires_top, FWireShellThickOut, halflength, SL, -1); + + //radius_layer_0 += FWradii; + + } else { + + delta_radius_layer = 2. * TMath::Pi() * radius_layerOut_0 / (num_wire - TMath::Pi()); + } + + //------------------------------------------------------------------------ + // Starting the layer loop. nLayer=8 + //------------------------------------------------------------------------ + + for (int ilayer = 0; ilayer < nLayer; ilayer++) { + //------------------------------------------------------------------------ + // Fill the geometry parameters of the layer. Each layer lies + // on top of the following one, so new layerIn = old layerOut + //------------------------------------------------------------------------ + + inscribedRadius = 0.5 * delta_radius_layer; + circumscribedRadius = inscribedRadius * sqrt(2.0); + senseWireRing_radius_0 = radius_layer_0 + inscribedRadius; + sign_epsilon *= -1; + + radius_layerIn_0 = radius_layerOut_0; + radius_layerIn = radius_layerOut; + epsilonIn = epsilonOut; + + radius_layerOut_0 = radius_layerIn_0 + FWireDiameter + 2.0 * secure; + radius_layerOut = radius_layerOut_0 + drop; + epsilonOut = atan(sqrt(diff_of_squares(radius_layerOut, radius_layerOut_0)) / halflength); + + zlength = halflength; + + // save bottom layer inner radius and epsilon before they are modified to build the whole layer hyperboloid volume + radius_layerIn_whole_cell = radius_layerIn_0; + epsilonIn_whole_cell = epsilonIn; + + //------------------------------------------------------------------------ + // Reduce zlength to avoid volume extrusions and check the staggering + //------------------------------------------------------------------------ + + zlength -= sin(epsilon) * FWradii; + zlength /= cos(epsilon); + + if (ilayer % 2 == 1) + cellStaggering = phi_layer; + else + cellStaggering = 0.0; + + //------------------------------------------------------------------------ + // Fill the field wire struct with all the relevant information + // This is the bottom of the cell. + //------------------------------------------------------------------------ + + field_wires_bottom.type = "F"; + field_wires_bottom.num = nFWire1; + field_wires_bottom.radius = radius_layerIn_0 + FWradii + extShiftFW; + field_wires_bottom.phi = phi_layer1; + field_wires_bottom.phioffset = layerangle + cellStaggering; + field_wires_bottom.stereo = sign_epsilon * epsilon; + field_wires_bottom.thickness = 0.5 * FWireShellThickIn * enlarge; + field_wires_bottom.halflength = zlength; + field_wires_bottom.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(ilayer, "_layer%d") + string("_type") + field_wires_bottom.type + dd4hep::_toString(field_wires_bottom.stereo, "_stereo%f_bottom"); + + //------------------------------------------------------------------------ + // Define the field wire name and build the field wire volume + //------------------------------------------------------------------------ + + lvFwireName = dd4hep::_toString(SL, "lvFwire_%d") + dd4hep::_toString(ilayer, "_%d"); + + dd4hep::Tube Fwire(0.0, field_wires_bottom.thickness, halflength); + lvFwireVol.push_back(dd4hep::Volume(lvFwireName, Fwire, description.material("G4_Al"))); + lvFwireVol.back().setVisAttributes(description, wirecol); + + //------------------------------------------------------------------------ + // Add the field wire volume to the struct + //------------------------------------------------------------------------ + + field_wires_bottom.volume = lvFwireVol.back(); + apply_wire_coating(field_wires_bottom, FWireShellThickOut, halflength); + + //------------------------------------------------------------------------ + // Next, fill the geometry parameters of the central layer. + //------------------------------------------------------------------------ + + iradius = radius_layer_0; + radius_layer_0 += delta_radius_layer; + drop = radius_layer_0 * dropFactor; + + radius_layerIn_0 = radius_layerOut_0; + radius_layerIn = radius_layerOut; + epsilonIn = epsilonOut; + radius_layerOut_0 = radius_layer_0 - FWireDiameter - 2.0 * secure; + radius_layerOut = radius_layerOut_0 + drop; + epsilonOut = atan(sqrt(diff_of_squares(radius_layerOut, radius_layerOut_0)) / halflength); + zlength = halflength; + + //------------------------------------------------------------------------ + // Reduce zlength to avoid volume extrusions + //------------------------------------------------------------------------ + + zlength -= sin(epsilon) * 0.5 * FWireShellThickIn; + zlength /= cos(epsilon); + + //------------------------------------------------------------------------ + // Fill the sense wire struct with all the relevant information + //------------------------------------------------------------------------ + + sense_wires.type = "S"; + sense_wires.num = num_wire; + sense_wires.radius = senseWireRing_radius_0; + sense_wires.phi = phi; + sense_wires.phioffset = cellStaggering; + sense_wires.stereo = sign_epsilon * epsilon; + sense_wires.thickness = 0.5 * SWireShellThickIn * enlarge; + sense_wires.halflength = zlength; + sense_wires.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(ilayer, "_layer%d") + string("_type") + sense_wires.type + dd4hep::_toString(sense_wires.stereo, "_stereo%f"); + + //------------------------------------------------------------------------ + // Define the sense wire name and build the sense wire volume + //------------------------------------------------------------------------ + + lvSwireName = dd4hep::_toString(SL, "lvSwire_%d") + dd4hep::_toString(ilayer, "_%d"); + + dd4hep::Tube Swire(0.0, sense_wires.thickness, halflength); + dd4hep::Volume lvSwireVol(lvSwireName, Swire, description.material("G4_W")); + lvSwireVol.setVisAttributes(description, wirecol); + sense_wires.volume = lvSwireVol; + apply_wire_coating(sense_wires, SWireShellThickOut, halflength, "G4_Au"); + + //------------------------------------------------------------------------ + // Tune the radius and epsilon of the central field wires + //------------------------------------------------------------------------ + + idelta_radius = delta_radius_layer * 0.5; + iradius += idelta_radius; + epsilon = atan(iradius * (1.0 + dropFactor) * epsilonFactor); + + //------------------------------------------------------------------------ + // Fill the central field wire struct with all the relevant information + //------------------------------------------------------------------------ + + field_wires_center.type = "F"; + field_wires_center.num = num_wire; + field_wires_center.radius = iradius; + field_wires_center.phi = phi; + field_wires_center.phioffset = layerangle + cellStaggering; + field_wires_center.stereo = sign_epsilon * epsilon; + field_wires_center.thickness = 0.5 * centerFWireShellThickIn * enlarge; + field_wires_center.halflength = zlength; + field_wires_center.volume = lvFwireVol.back(); + field_wires_center.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(ilayer, "_layer%d") + string("_type") + field_wires_center.type + dd4hep::_toString(field_wires_center.stereo, "_stereo%f_center"); + apply_wire_coating(field_wires_center, centerFWireShellThickOut, halflength); + + + //------------------------------------------------------------------------ + // Next, fill the geometry parameters of the upper layer. + //------------------------------------------------------------------------ + + radius_layerIn_0 = radius_layerOut_0; + radius_layerIn = radius_layerOut; + epsilonIn = epsilonOut; + radius_layerOut_0 = radius_layerIn_0 + FWireDiameter + 2.0 * secure; + radius_layerOut = radius_layerOut_0 + drop; + epsilonOut = atan(sqrt(diff_of_squares(radius_layerOut, radius_layerOut_0)) / halflength); + zlength = halflength; + + // Create hyperboloid volume of the whole layer for the cell sensitive volume definition + wholeHyperboloidVolumeName = dd4hep::_toString(SL, "hyperboloid_SL_%d") + dd4hep::_toString(ilayer, "_layer_%d"); + dd4hep::Hyperboloid whole_layer_hyperboloid = dd4hep::Hyperboloid(radius_layerIn_whole_cell, epsilonIn_whole_cell, radius_layerOut_0, epsilonOut, zlength); + dd4hep::Volume whole_layer_hyperboloid_volume = dd4hep::Volume(wholeHyperboloidVolumeName, whole_layer_hyperboloid, description.material("GasHe_90Isob_10")); + whole_layer_hyperboloid_volume.setVisAttributes(description, gascol); + //registerVolume(wholeHyperboloidVolumeName, whole_layer_hyperboloid_volume); + dd4hep::PlacedVolume whole_layer_hyperboloid_placedVolume; + whole_layer_hyperboloid_placedVolume = parentVol.placeVolume(whole_layer_hyperboloid_volume); + whole_layer_hyperboloid_placedVolume.addPhysVolID("superLayer", SL).addPhysVolID("layer", ilayer); + dd4hep::DetElement whole_layer_hyperboloid_detElement(parent, "superLayer_" + dd4hep::_toString(SL) + "_layer_" + dd4hep::_toString(ilayer) + "_hyperboloid", SL * nLayer + ilayer); + whole_layer_hyperboloid_detElement.setPlacement(whole_layer_hyperboloid_placedVolume); + + //------------------------------------------------------------------------ + // Reduce zlength to avoid volume extrusions + //------------------------------------------------------------------------ + + zlength -= sin(epsilon) * FWradii; + zlength /= cos(epsilon); + + //------------------------------------------------------------------------ + // Fill the field wire struct with all the relevant information + // This is the top of the cell. + //------------------------------------------------------------------------ + + field_wires_top.type = "F"; + field_wires_top.num = nFWire1; + field_wires_top.radius = radius_layerIn_0 - FWradii - extShiftFW; + field_wires_top.phi = phi_layer1; + field_wires_top.phioffset = layerangle + cellStaggering; + field_wires_top.stereo = sign_epsilon * epsilon; + field_wires_top.thickness = 0.5 * FWireShellThickIn * enlarge; + field_wires_top.halflength = zlength; + field_wires_top.volume = lvFwireVol.back(); + field_wires_top.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(ilayer, "_layer%d") + string("_type") + field_wires_top.type + dd4hep::_toString(field_wires_top.stereo, "_stereo%f_top"); + apply_wire_coating(field_wires_top, FWireShellThickOut, halflength); + + //if(setWireSensitive){ + // field_wires_bottom.volume.setSensitiveDetector(sens_det); + // field_wires_center.volume.setSensitiveDetector(sens_det); + // sense_wires.volume.setSensitiveDetector(sens_det); + // field_wires_top.volume.setSensitiveDetector(sens_det); + //} + + // arbitrarily extended tube section to build the sensitive volume ID associated to the wire from boolean operation with the layer hyperboloid + dd4hep::Tube cellID_tube_for_boolean(0, sense_wires.radius * 2, halflength, - sense_wires.phi / 2.0, sense_wires.phi / 2.0); + + // Radial translation + dd4hep::Translation3D radial_translation_sense_wire(sense_wires.radius, 0., 0.); + // stereo rotation + dd4hep::RotationX rot_stereo_sense_wire(sense_wires.stereo); + // extract the number of wire ratio to place field wires in the loop for sense wires + // it is not very elegant but the sense wire define the sensitive volume in which wires are placed + float middle_to_middle_num_wire_ratio = field_wires_center.num/float(sense_wires.num); + float middle_to_bottom_num_wire_ratio = field_wires_bottom.num/float(sense_wires.num); + float middle_to_top_num_wire_ratio = field_wires_top.num/float(sense_wires.num); + if(ceilf(middle_to_middle_num_wire_ratio) != middle_to_middle_num_wire_ratio || ceilf(middle_to_bottom_num_wire_ratio) != middle_to_bottom_num_wire_ratio || ceilf(middle_to_top_num_wire_ratio) != middle_to_top_num_wire_ratio) + throw std::runtime_error("Error: Failed to build CDCH. Please make sure that the number of wires in top/center cell rings is always a multiple of the number of wires in the middle of the cell"); + // loop to arrange the wires in phi, starting with the sense wires to be able to build the volume associated to the cell + for (int phi_index = 0; phi_index < sense_wires.num; phi_index++) { + // Prepare the cell sensitive volume as the intersection of the hyperboloid and a rotated tube segment + // phi rotation + dd4hep::RotationZ iRot(sense_wires.phioffset + sense_wires.phi * phi_index); + // complete transformation for the sense wires + dd4hep::Transform3D total_transformation(iRot * radial_translation_sense_wire * rot_stereo_sense_wire); + // create the intersection of the tube with the hyperboloid after rotating the tube in phi and stereo angle + dd4hep::IntersectionSolid cellID_shape = dd4hep::IntersectionSolid(whole_layer_hyperboloid, cellID_tube_for_boolean, dd4hep::Transform3D(dd4hep::RotationZ(sense_wires.phioffset + sense_wires.phi * phi_index) * dd4hep::RotationX(sense_wires.stereo))); + string cellID_volume_name = dd4hep::_toString(SL, "cellIDvolume_SL_%d") + dd4hep::_toString(ilayer, "_layer_%d") + dd4hep::_toString(phi_index, "_phi_%d"); + dd4hep::Volume cellID_volume = dd4hep::Volume(cellID_volume_name, cellID_shape, description.material("GasHe_90Isob_10")); + cellID_volume.setVisAttributes(description, gascol); + cellID_volume.setSensitiveDetector(sens_det); + dd4hep::PlacedVolume cellID_placedvolume = whole_layer_hyperboloid_volume.placeVolume(cellID_volume); + cellID_placedvolume.addPhysVolID("phi", phi_index).addPhysVolID("hitorigin", 0).addPhysVolID("stereo", sense_wires.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 0); + dd4hep::DetElement cellID_detElement(whole_layer_hyperboloid_detElement, "superLayer_" + dd4hep::_toString(SL) + "_layer_" + dd4hep::_toString(ilayer) + "_phi_" + dd4hep::_toString(phi_index) + "_cellID", phi_index); + cellID_detElement.setPlacement(cellID_placedvolume); + + // place the wires. The transformation is: apply the stereo angle rotation, translate the wire to the required radius, apply the phi rotation + // sense wires in the radial middle of the cell + dd4hep::PlacedVolume sense_wire_placedvolume = cellID_volume.placeVolume(sense_wires.volume, total_transformation); + // add the sense wire as detElement to be able to retrive its matrix with DD4hep 1.23 (with later verion we can use Volumes daugthers) + dd4hep::DetElement senseWire_detElement(cellID_detElement, "superLayer_" + dd4hep::_toString(SL) + "_layer_" + dd4hep::_toString(ilayer) + "_phi_" + dd4hep::_toString(phi_index) + "_wire", phi_index); + senseWire_detElement.setPlacement(sense_wire_placedvolume); + + // bottom field wires + for(int sub_phi_index = phi_index * middle_to_bottom_num_wire_ratio; sub_phi_index < (phi_index * middle_to_bottom_num_wire_ratio) + middle_to_bottom_num_wire_ratio; sub_phi_index++){ + dd4hep::PlacedVolume field_wire_bottom_placedvolume = cellID_volume.placeVolume(field_wires_bottom.volume, dd4hep::Transform3D(dd4hep::RotationZ(field_wires_bottom.phioffset + field_wires_bottom.phi * sub_phi_index) * dd4hep::Translation3D(field_wires_bottom.radius, 0., 0.) *dd4hep::RotationX(field_wires_bottom.stereo))); + //if(setWireSensitive) + // field_wire_bottom_placedvolume.addPhysVolID("phi", sub_phi_index).addPhysVolID("hitorigin", 2).addPhysVolID("stereo", field_wires_center.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 1); + } + + // central field wires + for(int sub_phi_index = phi_index * middle_to_middle_num_wire_ratio; sub_phi_index < (phi_index * middle_to_middle_num_wire_ratio) + middle_to_middle_num_wire_ratio; sub_phi_index++){ + dd4hep::PlacedVolume field_wire_center_placedvolume = cellID_volume.placeVolume(field_wires_center.volume, dd4hep::Transform3D(dd4hep::RotationZ(field_wires_center.phioffset + field_wires_center.phi * sub_phi_index) * dd4hep::Translation3D(field_wires_center.radius, 0., 0.) *dd4hep::RotationX(field_wires_center.stereo))); + //if(setWireSensitive) + // field_wire_center_placedvolume.addPhysVolID("phi", sub_phi_index).addPhysVolID("hitorigin", 2).addPhysVolID("stereo", field_wires_center.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 2); + } + + // top field wires + for(int sub_phi_index = phi_index * middle_to_top_num_wire_ratio; sub_phi_index < (phi_index * middle_to_top_num_wire_ratio) + middle_to_top_num_wire_ratio; sub_phi_index++){ + dd4hep::PlacedVolume field_wire_top_placedvolume = cellID_volume.placeVolume(field_wires_top.volume, dd4hep::Transform3D(dd4hep::RotationZ(field_wires_top.phioffset + field_wires_top.phi * sub_phi_index) * dd4hep::Translation3D(field_wires_top.radius, 0., 0.) *dd4hep::RotationX(field_wires_top.stereo))); + //if(setWireSensitive) + // field_wire_top_placedvolume.addPhysVolID("phi", sub_phi_index).addPhysVolID("hitorigin", 2).addPhysVolID("stereo", field_wires_center.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 3); + } + } + + //------------------------------------------------------------------------ + // Scale the delta radius of the layer for next iteration + //------------------------------------------------------------------------ + + delta_radius_layer *= scaleFactor; + } + + if (SL == (nSuperLayer - 1)) {// the last super layer is special since we need to add the field wires outside of the sensitive volume and the guard wires + + // Take care of the field wires outside of the sensitive volume + radius_layerIn_0 = radius_layerOut_0; + radius_layerIn = radius_layerOut; + epsilonIn = epsilonOut; + radius_layerOut_0 = radius_layer_0 + FWireDiameter + 2.0 * secure; + radius_layerOut = radius_layerOut_0 + drop; + epsilonOut = atan(sqrt(diff_of_squares(radius_layerOut, radius_layerOut_0)) / halflength); + + dd4hep::Hyperboloid HypeLayerOut(radius_layerIn_0, epsilonIn, radius_layerOut_0, epsilonOut, halflength); + lvLayerVol.push_back(dd4hep::Volume("hyperboloid_last_field_wire_ring", HypeLayerOut, description.material("GasHe_90Isob_10"))); + lvLayerVol.back().setVisAttributes(description, "vCDCH:Plastic"); + + zlength = halflength; + zlength -= sin(epsilon) * FWradii; + zlength /= cos(epsilon); + + field_wires_bottom.mother_volume = lvLayerVol.back(); + field_wires_bottom.type = "F"; + field_wires_bottom.num = nFWire1; + field_wires_bottom.radius = radius_layerIn_0 + FWradii + extShiftFW; + field_wires_bottom.phi = 2. * TMath::Pi() / field_wires_bottom.num; + field_wires_bottom.phioffset = layerangle + cellStaggering + phi_layer; + field_wires_bottom.stereo = -1. * sign_epsilon * epsilon; + field_wires_bottom.thickness = 0.5 * FWireShellThickIn * enlarge; + field_wires_bottom.halflength = zlength; + + lvFwireName = dd4hep::_toString(SL, "lvFwire_%d_out"); + field_wires_bottom.name = lvFwireName; + + dd4hep::Tube Fwire(0.0, field_wires_bottom.thickness, halflength); + lvFwireVol.push_back(dd4hep::Volume(lvFwireName, Fwire, description.material("G4_Al"))); + lvFwireVol.back().setVisAttributes(description, wirecol); + + field_wires_bottom.volume = lvFwireVol.back(); + CDCHBuild::PlaceWires(field_wires_bottom, FWireShellThickOut, halflength, SL, -1); + + //------------------------------------------------------------------------ + // Start placing the outer layer of guard wires (#guard wires == # field wires) + //------------------------------------------------------------------------ + + radius_layerIn_0 = radius_layerOut_0; + radius_layerIn = radius_layerOut; + epsilonIn = epsilonOut; + radius_layerOut_0 = radius_layer_0 + FWireDiameter + 2.0 * secure; + radius_layerOut = radius_layerOut_0 + drop; + epsilonOut = atan(sqrt(diff_of_squares(radius_layerOut, radius_layerOut_0)) / halflength); + + dd4hep::Hyperboloid HypeLayerOutG(radius_layerIn_0, epsilonOut, outer_radius - envelop_Outer_thickness - 0.0001, + 0.0, halflength); + lvLayerVol.push_back(dd4hep::Volume("hyperboloid_outer_guard_layer", HypeLayerOutG, description.material("GasHe_90Isob_10"))); + lvLayerVol.back().setVisAttributes(description, "vCDCH:Pb"); + + epsilonOutGwRing = atan(outGuardRad * (1.0 + dropFactor) * epsilonFactor); + zlength = halflength; + zlength -= sin(epsilonOutGwRing) * inGWradii; + zlength /= cos(epsilonOutGwRing); + + guard_wires.mother_volume = lvLayerVol.back(); + guard_wires.type = "G"; + guard_wires.num = nFWire1; + guard_wires.radius = outGuardRad - inGWradii; + guard_wires.phi = 2. * TMath::Pi() / guard_wires.num; + guard_wires.phioffset = layerangle; + guard_wires.stereo = epsilonOutGwRing; + guard_wires.thickness = 0.5 * OutGWireShellThickIn * enlarge; + guard_wires.halflength = zlength; + guard_wires.name = string("Gwire_outer_stereominus"); + + dd4hep::Tube Gwire(0.0, guard_wires.thickness, halflength); + lvGwireVol.push_back(dd4hep::Volume("Gwire_outer", Gwire, description.material("G4_Al"))); + lvGwireVol.back().setVisAttributes(description, wirecol); + + guard_wires.volume = lvGwireVol.back(); + CDCHBuild::PlaceWires(guard_wires, FWireShellThickOut, halflength, SL, -1); + + guard_wires.volume = lvGwireVol.back(); // needed because applyWireCoating acts on it + guard_wires.radius = outGuardRad + inGWradii + extShiftFW; + guard_wires.phioffset = layerangle + phi_layer; + guard_wires.stereo = -1.0 * epsilonOutGwRing; + guard_wires.name = string("Gwire_outer_stereoplus"); + CDCHBuild::PlaceWires(guard_wires, FWireShellThickOut, halflength, SL, -1); + } + } + + + Int_t sizeLayer = lvLayerVol.size(); + + + for (Int_t i = 0; i < sizeLayer; i++) { + registerVolume(lvLayerVol.at(i).name(), lvLayerVol.at(i)); + //cout << "Placing Volume: " << lvLayerVol.at(i).name() << endl; + //pv = parentVol.placeVolume(volume(lvLayerVol.at(i).name())); + //CDCHDetector.setPlacement(pv); + parentVol.placeVolume(volume(lvLayerVol.at(i).name())); + } + + double PosEndcapGas = halflength + 0.5 * GasEndcapWallThick; + double PosEndcapCopper = halflength + GasEndcapWallThick + 0.5 * CopperEndcapWallThick; + double PosEndcapKapton = halflength + GasEndcapWallThick + CopperEndcapWallThick + 0.5 * KaptonEndcapWallThick; + double PosEndcapCarbon = + halflength + GasEndcapWallThick + CopperEndcapWallThick + KaptonEndcapWallThick + 0.5 * CarbonEndcapWallThick; + + parentVol.placeVolume(lvInnerWallCarbon); + parentVol.placeVolume(lvInnerWallCopper); + parentVol.placeVolume(lvInnerWallGas); + parentVol.placeVolume(lvOuterWallCarbon1); + parentVol.placeVolume(lvOuterWallCarbon2); + parentVol.placeVolume(lvOuterWallCopper); + parentVol.placeVolume(lvOuterWallFoam); + parentVol.placeVolume(lvEndcapWallGas, dd4hep::Position(0., 0., PosEndcapGas)); + parentVol.placeVolume(lvEndcapWallCopper, dd4hep::Position(0., 0., PosEndcapCopper)); + parentVol.placeVolume(lvEndcapWallKapton, dd4hep::Position(0., 0., PosEndcapKapton)); + parentVol.placeVolume(lvEndcapWallCarbon, dd4hep::Position(0., 0., PosEndcapCarbon)); + parentVol.placeVolume(lvEndcapWallGas, dd4hep::Position(0., 0., -PosEndcapGas)); + parentVol.placeVolume(lvEndcapWallCopper, dd4hep::Position(0., 0., -PosEndcapCopper)); + parentVol.placeVolume(lvEndcapWallKapton, dd4hep::Position(0., 0., -PosEndcapKapton)); + parentVol.placeVolume(lvEndcapWallCarbon, dd4hep::Position(0., 0., -PosEndcapCarbon)); +} +} //namespace + +static dd4hep::Ref_t create_element(dd4hep::Detector& description, xml_h e, dd4hep::SensitiveDetector sens_det) { + + xml_det_t x_det = e; + CDCHBuild builder(description, x_det, sens_det); + string det_name = x_det.nameStr(); + + dd4hep::printout(dd4hep::DEBUG, "CreateCDCH", "Detector name: %s with ID: %s", det_name.c_str(), x_det.id()); + + DetElement CDCH_det = builder.detector; // ( det_name, x_det.id() ); + dd4hep::Tube CDCH_envelope(dd4hep::_toDouble("CDCH:r0"), dd4hep::_toDouble("CDCH:rOut"), dd4hep::_toDouble("CDCH:zHalfExtentWithServices")); + + dd4hep::Volume envelope("lvCDCH", CDCH_envelope, description.air()); + envelope.setVisAttributes(description, "vCDCH:Air"); + + // ****************************************************** + // Build CDCH cable + // ****************************************************** + + builder.build_layer(CDCH_det, envelope, sens_det); + + dd4hep::printout(dd4hep::DEBUG, "CreateCDCH", "MotherVolume is: %s", envelope.name()); + sens_det.setType("tracker"); + + builder.buildVolumes(e); + builder.placeDaughters(CDCH_det, envelope, e); + + // ****************************************************** + // Build CDCH cell and beam plug + // ****************************************************** + + // builder.build_cell(); + // builder.build_beamplug(); + + // ****************************************************** + // Assemble CDCH + // ****************************************************** + + // builder.build_CDCH( Ecal_det, envelope ); + + // ****************************************************** + // Place the CDCH in the world + // ****************************************************** + + PlacedVolume pv; + pv = builder.placeDetector(envelope); + pv.addPhysVolID("system", x_det.id()); + + return CDCH_det; +} + +DECLARE_DETELEMENT(DriftChamber_o1_v01, create_element) + diff --git a/detector/tracker/README.md b/detector/tracker/README.md index 5800e9f44..c7e2a1104 100644 --- a/detector/tracker/README.md +++ b/detector/tracker/README.md @@ -1,4 +1,6 @@ -# VertexBarrel_detailed and VertexDisks_detailed description +# Vertex detectors + +## VertexBarrel_detailed and VertexDisks_detailed description These two detector constructors were derived from ZPlanarTracker.cpp and from VertexEndcap_o1_v06.cpp and adapted to fit the needs of the [IDEA vertex detector engineering design](https://indico.cern.ch/event/1202105/timetable/#242-mechanical-integration-of). Both the barrel and the disks are made up of staves, that can feature an arbitrary number of cuboid layers to describe the support, readout and sensor structures. The sensors can be described by individual sensitive and insensitive pieces to form large, complex structures such as quad modules, that have an insensitive periphery. @@ -7,8 +9,19 @@ More details can be found in the talks at the [FCC week 2023](https://indico.cer # Trackers ## parametrised_SimplifiedDriftChamber -This sub-detector implements a simplied drift chamber. It is used in ALLEGRO detector concept. +This sub-detector implements a simplied drift chamber (there is no actual wire). It is used in ALLEGRO and IDEA detector concepts. ### o1_v01 Original version taken from [FCCDetectors](https://github.com/HEP-FCC/FCCDetectors/blob/70a989a6fc333610e3b1b979c3596da9c41543d8/Detector/DetFCChhCalDiscs/src/CaloEndcapDiscs_geo.cpp). +## DriftChamber +Detailed (i.e. including wires) description of a unique-volume, high granularity, fully stereo, low mass, cylindrical drift chamber. +Originally designed for the IDEA detector, it will be used also for the ALLEGRO concept with different dimensions. +A detailed description of the detector it tries to model can be found [here](https://indico.cern.ch/event/932973/contributions/4041314/attachments/2139657/3664808/primavera_FCCworkshop_2020.pdf) or [here](https://indico.cern.ch/event/1283129/contributions/5476695/attachments/2682660/4654170/DeFilippis_DCH_CC.pdf). + +### o1_v01 +First version with all wires, walls, etc. +This version do not rely on any external segmentation, all volumes are defined in the detector builder. +The sensitive cell volume is a rotated (to get the stereo angle) tube segment that are put inside a hyperboloid for each layer. +The hyperboloid is theoretically not needed, but it help a lot to have a well balanced volume tree. +This first version can clearly be improved and still suffers from some overlap but it already enables further technical developments (digitization, tracking, particle flow, ...). From 055031265afc4d1a7567c289df5e0221b74acfd7 Mon Sep 17 00:00:00 2001 From: BrieucF Date: Tue, 14 Nov 2023 11:07:04 +0100 Subject: [PATCH 10/29] [DriftChamber] Get rid of dd4hep::IntersectionSolid --- detector/tracker/DriftChamber_o1_v01.cpp | 34 +++++++++++------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/detector/tracker/DriftChamber_o1_v01.cpp b/detector/tracker/DriftChamber_o1_v01.cpp index a61b49163..656f5d501 100644 --- a/detector/tracker/DriftChamber_o1_v01.cpp +++ b/detector/tracker/DriftChamber_o1_v01.cpp @@ -637,7 +637,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti epsilonOut = atan(sqrt(diff_of_squares(radius_layerOut, radius_layerOut_0)) / halflength); zlength = halflength; - // Create hyperboloid volume of the whole layer for the cell sensitive volume definition + // Create hyperboloid volume of the whole layer for the cell sensitive volume definition, not needed per se but helps having a well balanced volume tree (having too many volumes inside one mother volume harms performance) wholeHyperboloidVolumeName = dd4hep::_toString(SL, "hyperboloid_SL_%d") + dd4hep::_toString(ilayer, "_layer_%d"); dd4hep::Hyperboloid whole_layer_hyperboloid = dd4hep::Hyperboloid(radius_layerIn_whole_cell, epsilonIn_whole_cell, radius_layerOut_0, epsilonOut, zlength); dd4hep::Volume whole_layer_hyperboloid_volume = dd4hep::Volume(wholeHyperboloidVolumeName, whole_layer_hyperboloid, description.material("GasHe_90Isob_10")); @@ -680,8 +680,8 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // field_wires_top.volume.setSensitiveDetector(sens_det); //} - // arbitrarily extended tube section to build the sensitive volume ID associated to the wire from boolean operation with the layer hyperboloid - dd4hep::Tube cellID_tube_for_boolean(0, sense_wires.radius * 2, halflength, - sense_wires.phi / 2.0, sense_wires.phi / 2.0); + // Create the tube segment volume to identify the cell sensitive regions (FIXME could be improved with e.g. extruded valumes or tessalatedSolids) + dd4hep::Tube cellID_tube_segment(radius_layerIn_whole_cell, radius_layerOut_0, halflength, - sense_wires.phi / 2.0, sense_wires.phi / 2.0); // Radial translation dd4hep::Translation3D radial_translation_sense_wire(sense_wires.radius, 0., 0.); @@ -694,48 +694,44 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti float middle_to_top_num_wire_ratio = field_wires_top.num/float(sense_wires.num); if(ceilf(middle_to_middle_num_wire_ratio) != middle_to_middle_num_wire_ratio || ceilf(middle_to_bottom_num_wire_ratio) != middle_to_bottom_num_wire_ratio || ceilf(middle_to_top_num_wire_ratio) != middle_to_top_num_wire_ratio) throw std::runtime_error("Error: Failed to build CDCH. Please make sure that the number of wires in top/center cell rings is always a multiple of the number of wires in the middle of the cell"); - // loop to arrange the wires in phi, starting with the sense wires to be able to build the volume associated to the cell + // loop to arrange the wires in phi, starting with the sense wires for (int phi_index = 0; phi_index < sense_wires.num; phi_index++) { - // Prepare the cell sensitive volume as the intersection of the hyperboloid and a rotated tube segment - // phi rotation - dd4hep::RotationZ iRot(sense_wires.phioffset + sense_wires.phi * phi_index); - // complete transformation for the sense wires - dd4hep::Transform3D total_transformation(iRot * radial_translation_sense_wire * rot_stereo_sense_wire); - // create the intersection of the tube with the hyperboloid after rotating the tube in phi and stereo angle - dd4hep::IntersectionSolid cellID_shape = dd4hep::IntersectionSolid(whole_layer_hyperboloid, cellID_tube_for_boolean, dd4hep::Transform3D(dd4hep::RotationZ(sense_wires.phioffset + sense_wires.phi * phi_index) * dd4hep::RotationX(sense_wires.stereo))); + // Place the sensitive volume inside the hyperbioloid with phi and stereo angle rotation string cellID_volume_name = dd4hep::_toString(SL, "cellIDvolume_SL_%d") + dd4hep::_toString(ilayer, "_layer_%d") + dd4hep::_toString(phi_index, "_phi_%d"); - dd4hep::Volume cellID_volume = dd4hep::Volume(cellID_volume_name, cellID_shape, description.material("GasHe_90Isob_10")); - cellID_volume.setVisAttributes(description, gascol); + dd4hep::Volume cellID_volume = dd4hep::Volume(cellID_volume_name, cellID_tube_segment, description.material("GasHe_90Isob_10")); cellID_volume.setSensitiveDetector(sens_det); - dd4hep::PlacedVolume cellID_placedvolume = whole_layer_hyperboloid_volume.placeVolume(cellID_volume); + // phi rotation + dd4hep::RotationZ rot_phi_sense_wire(sense_wires.phioffset + sense_wires.phi * phi_index); + dd4hep::PlacedVolume cellID_placedvolume = whole_layer_hyperboloid_volume.placeVolume(cellID_volume, dd4hep::Transform3D(rot_phi_sense_wire * rot_stereo_sense_wire)); cellID_placedvolume.addPhysVolID("phi", phi_index).addPhysVolID("hitorigin", 0).addPhysVolID("stereo", sense_wires.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 0); dd4hep::DetElement cellID_detElement(whole_layer_hyperboloid_detElement, "superLayer_" + dd4hep::_toString(SL) + "_layer_" + dd4hep::_toString(ilayer) + "_phi_" + dd4hep::_toString(phi_index) + "_cellID", phi_index); cellID_detElement.setPlacement(cellID_placedvolume); - // place the wires. The transformation is: apply the stereo angle rotation, translate the wire to the required radius, apply the phi rotation + // place the wires // sense wires in the radial middle of the cell - dd4hep::PlacedVolume sense_wire_placedvolume = cellID_volume.placeVolume(sense_wires.volume, total_transformation); + dd4hep::PlacedVolume sense_wire_placedvolume = cellID_volume.placeVolume(sense_wires.volume, dd4hep::Transform3D(radial_translation_sense_wire)); // only the radial translation is needed as the cellID volume already had the stereo and phi angle rotation // add the sense wire as detElement to be able to retrive its matrix with DD4hep 1.23 (with later verion we can use Volumes daugthers) dd4hep::DetElement senseWire_detElement(cellID_detElement, "superLayer_" + dd4hep::_toString(SL) + "_layer_" + dd4hep::_toString(ilayer) + "_phi_" + dd4hep::_toString(phi_index) + "_wire", phi_index); senseWire_detElement.setPlacement(sense_wire_placedvolume); + // FIXME the field wires are placed for now in the layer hyoperboloid envelope (with some overlap with the sensitive cell volume), should be improved when a better cell sensitive volume defnition is available // bottom field wires for(int sub_phi_index = phi_index * middle_to_bottom_num_wire_ratio; sub_phi_index < (phi_index * middle_to_bottom_num_wire_ratio) + middle_to_bottom_num_wire_ratio; sub_phi_index++){ - dd4hep::PlacedVolume field_wire_bottom_placedvolume = cellID_volume.placeVolume(field_wires_bottom.volume, dd4hep::Transform3D(dd4hep::RotationZ(field_wires_bottom.phioffset + field_wires_bottom.phi * sub_phi_index) * dd4hep::Translation3D(field_wires_bottom.radius, 0., 0.) *dd4hep::RotationX(field_wires_bottom.stereo))); + dd4hep::PlacedVolume field_wire_bottom_placedvolume = whole_layer_hyperboloid_volume.placeVolume(field_wires_bottom.volume, dd4hep::Transform3D(dd4hep::RotationZ(field_wires_bottom.phioffset + field_wires_bottom.phi * sub_phi_index) * dd4hep::Translation3D(field_wires_bottom.radius, 0., 0.) *dd4hep::RotationX(field_wires_bottom.stereo))); //if(setWireSensitive) // field_wire_bottom_placedvolume.addPhysVolID("phi", sub_phi_index).addPhysVolID("hitorigin", 2).addPhysVolID("stereo", field_wires_center.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 1); } // central field wires for(int sub_phi_index = phi_index * middle_to_middle_num_wire_ratio; sub_phi_index < (phi_index * middle_to_middle_num_wire_ratio) + middle_to_middle_num_wire_ratio; sub_phi_index++){ - dd4hep::PlacedVolume field_wire_center_placedvolume = cellID_volume.placeVolume(field_wires_center.volume, dd4hep::Transform3D(dd4hep::RotationZ(field_wires_center.phioffset + field_wires_center.phi * sub_phi_index) * dd4hep::Translation3D(field_wires_center.radius, 0., 0.) *dd4hep::RotationX(field_wires_center.stereo))); + dd4hep::PlacedVolume field_wire_center_placedvolume = whole_layer_hyperboloid_volume.placeVolume(field_wires_center.volume, dd4hep::Transform3D(dd4hep::RotationZ(field_wires_center.phioffset + field_wires_center.phi * sub_phi_index) * dd4hep::Translation3D(field_wires_center.radius, 0., 0.) *dd4hep::RotationX(field_wires_center.stereo))); //if(setWireSensitive) // field_wire_center_placedvolume.addPhysVolID("phi", sub_phi_index).addPhysVolID("hitorigin", 2).addPhysVolID("stereo", field_wires_center.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 2); } // top field wires for(int sub_phi_index = phi_index * middle_to_top_num_wire_ratio; sub_phi_index < (phi_index * middle_to_top_num_wire_ratio) + middle_to_top_num_wire_ratio; sub_phi_index++){ - dd4hep::PlacedVolume field_wire_top_placedvolume = cellID_volume.placeVolume(field_wires_top.volume, dd4hep::Transform3D(dd4hep::RotationZ(field_wires_top.phioffset + field_wires_top.phi * sub_phi_index) * dd4hep::Translation3D(field_wires_top.radius, 0., 0.) *dd4hep::RotationX(field_wires_top.stereo))); + dd4hep::PlacedVolume field_wire_top_placedvolume = whole_layer_hyperboloid_volume.placeVolume(field_wires_top.volume, dd4hep::Transform3D(dd4hep::RotationZ(field_wires_top.phioffset + field_wires_top.phi * sub_phi_index) * dd4hep::Translation3D(field_wires_top.radius, 0., 0.) *dd4hep::RotationX(field_wires_top.stereo))); //if(setWireSensitive) // field_wire_top_placedvolume.addPhysVolID("phi", sub_phi_index).addPhysVolID("hitorigin", 2).addPhysVolID("stereo", field_wires_center.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 3); } From ff54bfc3ec533a20c6254fa54d75164b8689e6b7 Mon Sep 17 00:00:00 2001 From: BrieucF Date: Tue, 14 Nov 2023 14:08:56 +0100 Subject: [PATCH 11/29] [DriftChamber] Field wires also in the cell volume (improves performance) --- detector/tracker/DriftChamber_o1_v01.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/detector/tracker/DriftChamber_o1_v01.cpp b/detector/tracker/DriftChamber_o1_v01.cpp index 656f5d501..f22018443 100644 --- a/detector/tracker/DriftChamber_o1_v01.cpp +++ b/detector/tracker/DriftChamber_o1_v01.cpp @@ -701,7 +701,8 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti dd4hep::Volume cellID_volume = dd4hep::Volume(cellID_volume_name, cellID_tube_segment, description.material("GasHe_90Isob_10")); cellID_volume.setSensitiveDetector(sens_det); // phi rotation - dd4hep::RotationZ rot_phi_sense_wire(sense_wires.phioffset + sense_wires.phi * phi_index); + double phi_angle_sense_wire_rotation = sense_wires.phioffset + sense_wires.phi * phi_index; + dd4hep::RotationZ rot_phi_sense_wire(phi_angle_sense_wire_rotation); dd4hep::PlacedVolume cellID_placedvolume = whole_layer_hyperboloid_volume.placeVolume(cellID_volume, dd4hep::Transform3D(rot_phi_sense_wire * rot_stereo_sense_wire)); cellID_placedvolume.addPhysVolID("phi", phi_index).addPhysVolID("hitorigin", 0).addPhysVolID("stereo", sense_wires.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 0); dd4hep::DetElement cellID_detElement(whole_layer_hyperboloid_detElement, "superLayer_" + dd4hep::_toString(SL) + "_layer_" + dd4hep::_toString(ilayer) + "_phi_" + dd4hep::_toString(phi_index) + "_cellID", phi_index); @@ -714,24 +715,30 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti dd4hep::DetElement senseWire_detElement(cellID_detElement, "superLayer_" + dd4hep::_toString(SL) + "_layer_" + dd4hep::_toString(ilayer) + "_phi_" + dd4hep::_toString(phi_index) + "_wire", phi_index); senseWire_detElement.setPlacement(sense_wire_placedvolume); - // FIXME the field wires are placed for now in the layer hyoperboloid envelope (with some overlap with the sensitive cell volume), should be improved when a better cell sensitive volume defnition is available + // field wires: the cellID volume has the stereo angle rotation of the sense wires which is different than the top/bototm wires --> Rotations are defined on top of the already applied cellID volume rotation // bottom field wires for(int sub_phi_index = phi_index * middle_to_bottom_num_wire_ratio; sub_phi_index < (phi_index * middle_to_bottom_num_wire_ratio) + middle_to_bottom_num_wire_ratio; sub_phi_index++){ - dd4hep::PlacedVolume field_wire_bottom_placedvolume = whole_layer_hyperboloid_volume.placeVolume(field_wires_bottom.volume, dd4hep::Transform3D(dd4hep::RotationZ(field_wires_bottom.phioffset + field_wires_bottom.phi * sub_phi_index) * dd4hep::Translation3D(field_wires_bottom.radius, 0., 0.) *dd4hep::RotationX(field_wires_bottom.stereo))); + // phi rotation + dd4hep::RotationZ rot_phi_bottom_wire((field_wires_bottom.phioffset + field_wires_bottom.phi * sub_phi_index) - phi_angle_sense_wire_rotation); + dd4hep::PlacedVolume field_wire_bottom_placedvolume = cellID_volume.placeVolume(field_wires_bottom.volume, dd4hep::Transform3D(rot_phi_bottom_wire * dd4hep::Translation3D(field_wires_bottom.radius, 0., 0.) * dd4hep::RotationX(field_wires_bottom.stereo - sense_wires.stereo))); //if(setWireSensitive) // field_wire_bottom_placedvolume.addPhysVolID("phi", sub_phi_index).addPhysVolID("hitorigin", 2).addPhysVolID("stereo", field_wires_center.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 1); } // central field wires for(int sub_phi_index = phi_index * middle_to_middle_num_wire_ratio; sub_phi_index < (phi_index * middle_to_middle_num_wire_ratio) + middle_to_middle_num_wire_ratio; sub_phi_index++){ - dd4hep::PlacedVolume field_wire_center_placedvolume = whole_layer_hyperboloid_volume.placeVolume(field_wires_center.volume, dd4hep::Transform3D(dd4hep::RotationZ(field_wires_center.phioffset + field_wires_center.phi * sub_phi_index) * dd4hep::Translation3D(field_wires_center.radius, 0., 0.) *dd4hep::RotationX(field_wires_center.stereo))); + // phi rotation + dd4hep::RotationZ rot_phi_center_wire((field_wires_center.phioffset + field_wires_center.phi * sub_phi_index) - phi_angle_sense_wire_rotation); + dd4hep::PlacedVolume field_wire_center_placedvolume = cellID_volume.placeVolume(field_wires_center.volume, dd4hep::Transform3D(rot_phi_center_wire * dd4hep::Translation3D(field_wires_center.radius, 0., 0.) * dd4hep::RotationX(field_wires_center.stereo - sense_wires.stereo))); //if(setWireSensitive) // field_wire_center_placedvolume.addPhysVolID("phi", sub_phi_index).addPhysVolID("hitorigin", 2).addPhysVolID("stereo", field_wires_center.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 2); } // top field wires for(int sub_phi_index = phi_index * middle_to_top_num_wire_ratio; sub_phi_index < (phi_index * middle_to_top_num_wire_ratio) + middle_to_top_num_wire_ratio; sub_phi_index++){ - dd4hep::PlacedVolume field_wire_top_placedvolume = whole_layer_hyperboloid_volume.placeVolume(field_wires_top.volume, dd4hep::Transform3D(dd4hep::RotationZ(field_wires_top.phioffset + field_wires_top.phi * sub_phi_index) * dd4hep::Translation3D(field_wires_top.radius, 0., 0.) *dd4hep::RotationX(field_wires_top.stereo))); + // phi rotation + dd4hep::RotationZ rot_phi_top_wire((field_wires_top.phioffset + field_wires_top.phi * sub_phi_index) - phi_angle_sense_wire_rotation); + dd4hep::PlacedVolume field_wire_top_placedvolume = cellID_volume.placeVolume(field_wires_top.volume, dd4hep::Transform3D(rot_phi_top_wire * dd4hep::Translation3D(field_wires_top.radius, 0., 0.) * dd4hep::RotationX(field_wires_top.stereo - sense_wires.stereo))); //if(setWireSensitive) // field_wire_top_placedvolume.addPhysVolID("phi", sub_phi_index).addPhysVolID("hitorigin", 2).addPhysVolID("stereo", field_wires_center.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 3); } From 509dab7e34b0095e77e00043214d69044f94bad8 Mon Sep 17 00:00:00 2001 From: BrieucF Date: Tue, 21 Nov 2023 13:37:26 +0100 Subject: [PATCH 12/29] [DriftChamber] First batch of cleaning/commenting --- .../DectDimensions_IDEA_o1_v01.xml | 2 +- .../IDEA_o1_v02/DriftChamber_o1_v01.xml | 26 ++- detector/tracker/DriftChamber_o1_v01.cpp | 203 +++++------------- 3 files changed, 69 insertions(+), 162 deletions(-) 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 8211dbdf2..27a5bb4fc 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 @@ -89,7 +89,7 @@ - + diff --git a/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml index f70ad90a0..dd58fc0fa 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml @@ -7,24 +7,28 @@ - - + + + + + - - - - + + + - + + + - - + + diff --git a/detector/tracker/DriftChamber_o1_v01.cpp b/detector/tracker/DriftChamber_o1_v01.cpp index f22018443..5f83e30a0 100644 --- a/detector/tracker/DriftChamber_o1_v01.cpp +++ b/detector/tracker/DriftChamber_o1_v01.cpp @@ -39,7 +39,7 @@ struct CDCHBuild : public dd4hep::xml::tools::VolumeBuilder { double diff_of_squares(double a, double b); void apply_wire_coating(struct wire& w, double outwrap, double halflength, string material); - void PlaceWires(struct wire& w, double outwrap, double halflength, int SL, int ilayer); + void PlaceGuardWires(struct wire& w, double outwrap, double halflength, int SL, int ilayer); void build_layer(DetElement parent, Volume parentVol, dd4hep::SensitiveDetector sens); }; @@ -66,8 +66,7 @@ void CDCHBuild::apply_wire_coating(struct wire& w, double outwrap, double halfle w.volume = WireVol; } -// deprecated function, only use it for the wires before and after the sensitive zone (mainly guard wires) -void CDCHBuild::PlaceWires(struct wire& w, double outwrap, double halflength, int SL = 999, +void CDCHBuild::PlaceGuardWires(struct wire& w, double outwrap, double halflength, int SL = 999, int ilayer = 999) { dd4hep::RotationZYX rot(0., 0., w.stereo); @@ -85,8 +84,6 @@ void CDCHBuild::PlaceWires(struct wire& w, double outwrap, double halflength, in wirewrapname += "_stereo"; wirewrapname += std::to_string(w.stereo); - //cout << "wirewrapname: " << wirewrapname << endl; - string wirename = "Wire_SL"; wirename += std::to_string(SL); wirename += "_layer"; @@ -98,9 +95,6 @@ void CDCHBuild::PlaceWires(struct wire& w, double outwrap, double halflength, in apply_wire_coating(w, outwrap, halflength); - // registerVolume(WireWrapVol.name(), WireWrapVol); - // registerVolume(WireVol.name(), WireVol); - // repeat the placement of wires over phi for (int n = 0; n < w.num; n++) { dd4hep::RotationZ iRot(w.phioffset + w.phi * n); @@ -115,8 +109,8 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // ****************************************************** double halfalpha = 0.5 * dd4hep::_toDouble("CDCH:alpha"); - double inner_radius = dd4hep::_toDouble("CDCH:r0"); - double outer_radius = dd4hep::_toDouble("CDCH:rOut"); + double inner_radius = dd4hep::_toDouble("CDCH:inner_radius"); + double outer_radius = dd4hep::_toDouble("CDCH:outer_radius"); double zHalfExtentWithServices = dd4hep::_toDouble("CDCH:zHalfExtentWithServices"); double CarbonInnerWallThick = dd4hep::_toDouble("CDCH:CarbonInnerWallThick"); double CopperInnerWallThick = dd4hep::_toDouble("CDCH:CopperInnerWallThick"); @@ -138,7 +132,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double InGWireShellThickIn = dd4hep::_toDouble("CDCH:InGWireShellThickIn"); double InGWireShellThickOut = dd4hep::_toDouble("CDCH:InGWireShellThickOut"); double OutGWireShellThickIn = dd4hep::_toDouble("CDCH:InGWireShellThickIn"); - double OutGWireShellThickOut = dd4hep::_toDouble("CDCH:InGWireShellThickOut"); + //double OutGWireShellThickOut = dd4hep::_toDouble("CDCH:InGWireShellThickOut"); double secure = dd4hep::_toDouble("CDCH:secure"); double capGasLayer = dd4hep::_toDouble("CDCH:capGasLayer"); double extShiftFW = dd4hep::_toDouble("CDCH:extShiftFW"); @@ -146,12 +140,12 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double inGuardRad = dd4hep::_toDouble("CDCH:inGuardRad"); double outGuardRad = dd4hep::_toDouble("CDCH:outGuardRad"); int nSDeltaWire = dd4hep::_toInt("CDCH:nSDeltaWire"); - int nSWire = dd4hep::_toInt("CDCH:nSWire"); + int nSWireFirstLayer = dd4hep::_toInt("CDCH:nSWireFirstLayer"); int nStoFWireRatio = dd4hep::_toInt("CDCH:nStoFWireRatio"); int nVerticalFWire = dd4hep::_toInt("CDCH:nVerticalFWire"); int nSuperLayer = dd4hep::_toInt("CDCH:nSuperLayer"); int nLayer = dd4hep::_toInt("CDCH:nLayer"); - int nFieldWireShells = dd4hep::_toInt("CDCH:nFieldWireShells"); + //int nFieldWireShells = dd4hep::_toInt("CDCH:nFieldWireShells"); //bool setWireSensitive = true; // FIXME: add the possibility to have wires sensitive (parameter in the xml) which could be useful for detailed chamber behavior studies, current attempt never lead to a hit in the wire, even with enlarged wires... double halflength = zHalfExtentWithServices - (GasEndcapWallThick + CopperEndcapWallThick + KaptonEndcapWallThick + CarbonEndcapWallThick); // this will be the sensitive volume z extent @@ -159,11 +153,11 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double phi_layer = 0.0; double phi_layer1 = 0.0; int nFWire = 0; - int nFWire1 = 0; - int num_wire = 0; + int nFWireTopAndBottom = 0; + int nSWire = 0; int nHorizontalFWire = nStoFWireRatio - nVerticalFWire; int sign_epsilon = -1; - double phi = 0.0; + double cell_phi_coverage = 0.0; double scaleFactor = 0.0; double dropFactor = 0.0; double epsilonFactor = 0.0; @@ -177,8 +171,8 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti Carbon1OuterWallThick + Carbon2OuterWallThick + CopperOuterWallThick + FoamOuterWallThick; double FWireDiameter = FWireShellThickIn + FWireShellThickOut; double FWradii = 0.5 * FWireDiameter; - double SWireDiameter = SWireShellThickIn + SWireShellThickOut; - double SWradii = 0.5 * SWireDiameter; + //double SWireDiameter = SWireShellThickIn + SWireShellThickOut; + //double SWradii = 0.5 * SWireDiameter; double inGWireDiameter = InGWireShellThickIn + InGWireShellThickOut; double inGWradii = 0.5 * inGWireDiameter; double fakeLayerInIWthick = -0.0001 + GasInnerWallThick; @@ -195,9 +189,9 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double epsilonIn = 0.0; double epsilonOut = 0.0; double layerangle = 0.0; - double cellBase = 0.0; + //double cellBase = 0.0; double inscribedRadius = 0.0; - double circumscribedRadius = 0.0; + //double circumscribedRadius = 0.0; double zlength = 0.0; double cellStaggering = 0.0; double epsilonInGwRing = 0.0; @@ -246,7 +240,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti outer_radius - Carbon1OuterWallThick - Carbon2OuterWallThick - FoamOuterWallThick, halflength); dd4hep::Tube OuterWall_Carbon1(outer_radius - Carbon1OuterWallThick - Carbon2OuterWallThick - FoamOuterWallThick, - outer_radius - Carbon2OuterWallThick - FoamOuterWallThick, halflength);// FIXME there is an overlap with OuterWall_Carbon1 and the last guard wire layer + outer_radius - Carbon2OuterWallThick - FoamOuterWallThick, halflength); dd4hep::Tube OuterWall_Foam(outer_radius - Carbon2OuterWallThick - FoamOuterWallThick, outer_radius - Carbon2OuterWallThick, halflength); dd4hep::Tube OuterWall_Carbon2(outer_radius - Carbon2OuterWallThick, outer_radius, halflength); @@ -272,22 +266,21 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti string lvFwireName, lvSwireName; struct wire guard_wires{}, field_wires_bottom{}, field_wires_center{}, field_wires_top{}, sense_wires{}; - // nSuperLayer = 1; for (int SL = 0; SL < nSuperLayer; ++SL) { - num_wire = nSWire + SL * nSDeltaWire; - phi = 2. * TMath::Pi() / num_wire; - nFWire = nHorizontalFWire * num_wire; + nSWire = nSWireFirstLayer + SL * nSDeltaWire; + cell_phi_coverage = 2. * TMath::Pi() / nSWire; + nFWire = nHorizontalFWire * nSWire; phi_layer = 2. * TMath::Pi() / nFWire; - nFWire1 = nFWire / 2; - if (ceilf(nFWire1) != nFWire1) - throw std::runtime_error("Error: Failed to build CDCH. Please make sure that '(nStoFWireRatio - nVerticalFWire) * (nSWire + SuperLayerIndex * nSDeltaWire)' is always an even number"); + nFWireTopAndBottom = nFWire / 2; + if (ceilf(nFWireTopAndBottom) != nFWireTopAndBottom) + throw std::runtime_error("Error: Failed to build CDCH. Please make sure that '(nStoFWireRatio - nVerticalFWire) * (nSWireFirstLayer + SuperLayerIndex * nSDeltaWire)' is always an even number"); phi_layer1 = 2.0 * phi_layer; - scaleFactor = (1.0 + TMath::Pi() / num_wire) / (1.0 - TMath::Pi() / num_wire); + scaleFactor = (1.0 + TMath::Pi() / nSWire) / (1.0 - TMath::Pi() / nSWire); dropFactor = (1.0 / cos(halfalpha) - 1.0); // used to determine the radius of the hyperboloid in z = +- halflength with r_out = r_min + r_min * dropFactor epsilonFactor = sin(halfalpha) / halflength; - layerangle = -0.5 * phi; + layerangle = -0.5 * cell_phi_coverage; gascol = "vCDCH:Gas1"; if (SL % 3 == 0) @@ -318,7 +311,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti guard_wires.mother_volume = lvLayerVol.back(); guard_wires.type = "G"; - guard_wires.num = nFWire1; //(#guard wires == # field wires) + guard_wires.num = nFWireTopAndBottom; //(#guard wires == # field wires) guard_wires.radius = inGuardRad - inGWradii; guard_wires.phi = 2. * TMath::Pi() / guard_wires.num; guard_wires.phioffset = layerangle; @@ -332,14 +325,14 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti lvGwireVol.back().setVisAttributes(description, wirecol); guard_wires.volume = lvGwireVol.back(); - CDCHBuild::PlaceWires(guard_wires, FWireShellThickOut, halflength, SL, -1); + CDCHBuild::PlaceGuardWires(guard_wires, FWireShellThickOut, halflength, SL, -1); guard_wires.volume = lvGwireVol.back(); // needed because applyWireCoating acts on it guard_wires.radius = inGuardRad + inGWradii + extShiftFW; guard_wires.phioffset = layerangle + phi_layer; guard_wires.stereo = -1.0 * epsilonInGwRing; guard_wires.name = string("Gwire_inner_stereominus"); - CDCHBuild::PlaceWires(guard_wires, FWireShellThickOut, halflength, SL, -1); + CDCHBuild::PlaceGuardWires(guard_wires, FWireShellThickOut, halflength, SL, -1); drop = radius_layer_0 * dropFactor; radius_layer = radius_layer_0 + drop; @@ -361,7 +354,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_top.mother_volume = lvLayerVol.back(); field_wires_top.type = "F"; - field_wires_top.num = nFWire1; + field_wires_top.num = nFWireTopAndBottom; field_wires_top.radius = radius_layerIn_0 - FWradii - extShiftFW; field_wires_top.phi = 2. * TMath::Pi() /field_wires_top.num;; field_wires_top.phioffset = layerangle + cellStaggering - phi_layer; @@ -377,105 +370,12 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti lvFwireVol.back().setVisAttributes(description, wirecol); field_wires_top.volume = lvFwireVol.back(); - CDCHBuild::PlaceWires(field_wires_top, FWireShellThickOut, halflength, SL, -1); + CDCHBuild::PlaceGuardWires(field_wires_top, FWireShellThickOut, halflength, SL, -1); radius_layer_0 += FWradii; - - - // the commented part below is a trial to get totally rid of PlaceWire function and to treat wires outside of the sensitive volume the same way as the one inside - - //// deal with the first guard layer - //double stereoOut0 = atan((radius_layerOut_0 + FWradii) * (1.0 * dropFactor * epsilonFactor)); - ////stereoOut0 = atan(sqrt(diff_of_squares(radius_layerOut_0 + FWradii, - - ////radius_layerOut_0 = radius_layerIn_0 + FWireDiameter + 2.0 * secure; - ////radius_layerOut = radius_layerOut_0 + drop; - ////epsilonOut = atan(sqrt(diff_of_squares(radius_layerOut, radius_layerOut_0)) / halflength); - ////dd4hep::Hyperboloid HypeLayer0(inner_radius_0, 0.0, radius_layerOut_0 + FWradii - secure, stereoOut0, halflength); - //dd4hep::Hyperboloid HypeLayer0(inner_radius_0, 0.0, radius_layerOut_0 + FWradii, stereoOut0, halflength); - //dd4hep::Volume inner_guard_layer_volume("hyperboloid_inner_guard_layer", HypeLayer0, description.material("GasHe_90Isob_10")); - //dd4hep::PlacedVolume inner_guard_layer_placedVolume = parentVol.placeVolume(inner_guard_layer_volume); - //CDCHDetector.setPlacement(inner_guard_layer_placedVolume); - - //epsilonInGwRing = atan(inGuardRad * (1.0 + dropFactor) * epsilonFactor); - //zlength = halflength; - //zlength -= sin(epsilonInGwRing) * inGWradii; - //zlength /= cos(epsilonInGwRing); - - //guard_wires.mother_volume = inner_guard_layer_volume; - //guard_wires.type = "G"; - //guard_wires.num = nInGWire; - //guard_wires.radius = inGuardRad - inGWradii; - //guard_wires.phi = 2. * TMath::Pi() / guard_wires.num; - //guard_wires.phioffset = layerangle; - //guard_wires.stereo = epsilonInGwRing; - //guard_wires.thickness = 0.5 * InGWireShellThickIn * enlarge; // half the inner thickness as radius of tube - //guard_wires.halflength = zlength; - //guard_wires.name = string("InnerGuardWire") + dd4hep::_toString(guard_wires.stereo, "_stereo%f"); - //dd4hep::Tube Gwire(0.0, guard_wires.thickness, halflength); - //guard_wires.volume = dd4hep::Volume("InnerGuardWire", Gwire, description.material("G4_Al")); - //apply_wire_coating(guard_wires, InGWireShellThickIn, halflength); - //// Radial translation - //dd4hep::Translation3D radial_translation_guard_wire(guard_wires.radius, 0., 0.); - //// stereo rotation - //dd4hep::RotationX rot_stereo_guard_wire(guard_wires.stereo); - //dd4hep::PlacedVolume inner_guard_wire_placedvolume; - //for (int phi_index = 0; phi_index < guard_wires.num; phi_index++) { - // dd4hep::RotationZ iRot(guard_wires.phioffset + guard_wires.phi * phi_index); - // dd4hep::Transform3D total_transformation(iRot * radial_translation_guard_wire * rot_stereo_guard_wire); - // inner_guard_wire_placedvolume = inner_guard_layer_volume.placeVolume(guard_wires.volume, total_transformation); - // //if(setWireSensitive) - // // inner_guard_wire_placedvolume.addPhysVolID("phi", phi_index).addPhysVolID("hitorigin", 3).addPhysVolID("stereo", guard_wires.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 0); - //} - - //guard_wires.radius = inGuardRad + inGWradii + extShiftFW; - //guard_wires.phioffset = layerangle + phi_layer; - //guard_wires.stereo = -1.0 * epsilonInGwRing; - //guard_wires.name = string("InnerGuardWire") + dd4hep::_toString(guard_wires.stereo, "_stereo%f"); - - //drop = radius_layer_0 * dropFactor; - //radius_layer = radius_layer_0 + drop; - //epsilon = atan(radius_layer * epsilonFactor); - //radius_layerIn_0 = radius_layer_0 - FWradii - 2.0 * secure; - //radius_layerIn = radius_layerIn_0 + drop; - //radius_layerOut_0 = radius_layer_0 + FWradii; - //radius_layerOut = radius_layerOut_0 + drop; - //epsilonIn = atan(sqrt(pow(radius_layerIn, 2) - pow(radius_layerIn_0, 2)) / halflength); - //epsilonOut = atan(sqrt(pow(radius_layerOut, 2) - pow(radius_layerOut_0, 2)) / halflength); - - //dd4hep::Hyperboloid HypeLayer1(radius_layerIn_0, epsilonIn, radius_layerOut_0, epsilonOut, halflength); - //lvLayerVol.push_back(dd4hep::Volume("lvLayer_0", HypeLayer1, description.material("GasHe_90Isob_10"))); - //lvLayerVol.back().setVisAttributes(description, "vCDCH:Plastic"); - - //zlength = halflength; - //zlength -= sin(epsilon) * FWradii; - //zlength /= cos(epsilon); - - //field_wires_top.mother_volume = lvLayerVol.back(); - //field_wires_top.type = "F"; - //field_wires_top.num = nFWire1; - //field_wires_top.radius = radius_layerIn_0 - FWradii - extShiftFW; - //field_wires_top.phi = phi_layer1; - //field_wires_top.phioffset = layerangle + cellStaggering - phi_layer; - //field_wires_top.stereo = sign_epsilon * epsilon; - //field_wires_top.thickness = 0.5 * FWireShellThickIn * enlarge; - //field_wires_top.halflength = zlength; - //field_wires_top.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(-1, "_layer%d") + string("_type") + field_wires_top.type + dd4hep::_toString(field_wires_top.stereo, "_stereo%f_top"); - - //lvFwireName = dd4hep::_toString(SL, "lvFwire_%d_init"); - - //dd4hep::Tube Fwire(0.0, field_wires_top.thickness, halflength); - //lvFwireVol.push_back(dd4hep::Volume(lvFwireName, Fwire, description.material("G4_Al"))); - //lvFwireVol.back().setVisAttributes(description, wirecol); - - ////field_wires_top.volume = lvFwireVol.back(); - //////CDCHBuild::PlaceWires(field_wires_top, FWireShellThickOut, halflength, SL, -1); - - //radius_layer_0 += FWradii; } else { - - delta_radius_layer = 2. * TMath::Pi() * radius_layerOut_0 / (num_wire - TMath::Pi()); + delta_radius_layer = 2. * TMath::Pi() * radius_layerOut_0 / (nSWire - TMath::Pi()); } //------------------------------------------------------------------------ @@ -489,7 +389,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti //------------------------------------------------------------------------ inscribedRadius = 0.5 * delta_radius_layer; - circumscribedRadius = inscribedRadius * sqrt(2.0); + //circumscribedRadius = inscribedRadius * sqrt(2.0); senseWireRing_radius_0 = radius_layer_0 + inscribedRadius; sign_epsilon *= -1; @@ -525,7 +425,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti //------------------------------------------------------------------------ field_wires_bottom.type = "F"; - field_wires_bottom.num = nFWire1; + field_wires_bottom.num = nFWireTopAndBottom; field_wires_bottom.radius = radius_layerIn_0 + FWradii + extShiftFW; field_wires_bottom.phi = phi_layer1; field_wires_bottom.phioffset = layerangle + cellStaggering; @@ -541,14 +441,14 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti lvFwireName = dd4hep::_toString(SL, "lvFwire_%d") + dd4hep::_toString(ilayer, "_%d"); dd4hep::Tube Fwire(0.0, field_wires_bottom.thickness, halflength); - lvFwireVol.push_back(dd4hep::Volume(lvFwireName, Fwire, description.material("G4_Al"))); - lvFwireVol.back().setVisAttributes(description, wirecol); + dd4hep::Volume FwireVol(lvFwireName, Fwire, description.material("G4_Al")); + FwireVol.setVisAttributes(description, wirecol); //------------------------------------------------------------------------ // Add the field wire volume to the struct //------------------------------------------------------------------------ - field_wires_bottom.volume = lvFwireVol.back(); + field_wires_bottom.volume = FwireVol; apply_wire_coating(field_wires_bottom, FWireShellThickOut, halflength); //------------------------------------------------------------------------ @@ -579,9 +479,9 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti //------------------------------------------------------------------------ sense_wires.type = "S"; - sense_wires.num = num_wire; + sense_wires.num = nSWire; sense_wires.radius = senseWireRing_radius_0; - sense_wires.phi = phi; + sense_wires.phi = cell_phi_coverage; sense_wires.phioffset = cellStaggering; sense_wires.stereo = sign_epsilon * epsilon; sense_wires.thickness = 0.5 * SWireShellThickIn * enlarge; @@ -613,14 +513,14 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti //------------------------------------------------------------------------ field_wires_center.type = "F"; - field_wires_center.num = num_wire; + field_wires_center.num = nSWire; field_wires_center.radius = iradius; - field_wires_center.phi = phi; + field_wires_center.phi = cell_phi_coverage; field_wires_center.phioffset = layerangle + cellStaggering; field_wires_center.stereo = sign_epsilon * epsilon; field_wires_center.thickness = 0.5 * centerFWireShellThickIn * enlarge; field_wires_center.halflength = zlength; - field_wires_center.volume = lvFwireVol.back(); + field_wires_center.volume = FwireVol; field_wires_center.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(ilayer, "_layer%d") + string("_type") + field_wires_center.type + dd4hep::_toString(field_wires_center.stereo, "_stereo%f_center"); apply_wire_coating(field_wires_center, centerFWireShellThickOut, halflength); @@ -662,14 +562,14 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti //------------------------------------------------------------------------ field_wires_top.type = "F"; - field_wires_top.num = nFWire1; + field_wires_top.num = nFWireTopAndBottom; field_wires_top.radius = radius_layerIn_0 - FWradii - extShiftFW; field_wires_top.phi = phi_layer1; field_wires_top.phioffset = layerangle + cellStaggering; field_wires_top.stereo = sign_epsilon * epsilon; field_wires_top.thickness = 0.5 * FWireShellThickIn * enlarge; field_wires_top.halflength = zlength; - field_wires_top.volume = lvFwireVol.back(); + field_wires_top.volume = FwireVol; field_wires_top.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(ilayer, "_layer%d") + string("_type") + field_wires_top.type + dd4hep::_toString(field_wires_top.stereo, "_stereo%f_top"); apply_wire_coating(field_wires_top, FWireShellThickOut, halflength); @@ -720,7 +620,8 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti for(int sub_phi_index = phi_index * middle_to_bottom_num_wire_ratio; sub_phi_index < (phi_index * middle_to_bottom_num_wire_ratio) + middle_to_bottom_num_wire_ratio; sub_phi_index++){ // phi rotation dd4hep::RotationZ rot_phi_bottom_wire((field_wires_bottom.phioffset + field_wires_bottom.phi * sub_phi_index) - phi_angle_sense_wire_rotation); - dd4hep::PlacedVolume field_wire_bottom_placedvolume = cellID_volume.placeVolume(field_wires_bottom.volume, dd4hep::Transform3D(rot_phi_bottom_wire * dd4hep::Translation3D(field_wires_bottom.radius, 0., 0.) * dd4hep::RotationX(field_wires_bottom.stereo - sense_wires.stereo))); + cellID_volume.placeVolume(field_wires_bottom.volume, dd4hep::Transform3D(rot_phi_bottom_wire * dd4hep::Translation3D(field_wires_bottom.radius, 0., 0.) * dd4hep::RotationX(field_wires_bottom.stereo - sense_wires.stereo))); + //dd4hep::PlacedVolume field_wire_bottom_placedvolume = cellID_volume.placeVolume(field_wires_bottom.volume, dd4hep::Transform3D(rot_phi_bottom_wire * dd4hep::Translation3D(field_wires_bottom.radius, 0., 0.) * dd4hep::RotationX(field_wires_bottom.stereo - sense_wires.stereo))); //if(setWireSensitive) // field_wire_bottom_placedvolume.addPhysVolID("phi", sub_phi_index).addPhysVolID("hitorigin", 2).addPhysVolID("stereo", field_wires_center.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 1); } @@ -729,7 +630,8 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti for(int sub_phi_index = phi_index * middle_to_middle_num_wire_ratio; sub_phi_index < (phi_index * middle_to_middle_num_wire_ratio) + middle_to_middle_num_wire_ratio; sub_phi_index++){ // phi rotation dd4hep::RotationZ rot_phi_center_wire((field_wires_center.phioffset + field_wires_center.phi * sub_phi_index) - phi_angle_sense_wire_rotation); - dd4hep::PlacedVolume field_wire_center_placedvolume = cellID_volume.placeVolume(field_wires_center.volume, dd4hep::Transform3D(rot_phi_center_wire * dd4hep::Translation3D(field_wires_center.radius, 0., 0.) * dd4hep::RotationX(field_wires_center.stereo - sense_wires.stereo))); + cellID_volume.placeVolume(field_wires_center.volume, dd4hep::Transform3D(rot_phi_center_wire * dd4hep::Translation3D(field_wires_center.radius, 0., 0.) * dd4hep::RotationX(field_wires_center.stereo - sense_wires.stereo))); + //dd4hep::PlacedVolume field_wire_center_placedvolume = cellID_volume.placeVolume(field_wires_center.volume, dd4hep::Transform3D(rot_phi_center_wire * dd4hep::Translation3D(field_wires_center.radius, 0., 0.) * dd4hep::RotationX(field_wires_center.stereo - sense_wires.stereo))); //if(setWireSensitive) // field_wire_center_placedvolume.addPhysVolID("phi", sub_phi_index).addPhysVolID("hitorigin", 2).addPhysVolID("stereo", field_wires_center.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 2); } @@ -738,7 +640,8 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti for(int sub_phi_index = phi_index * middle_to_top_num_wire_ratio; sub_phi_index < (phi_index * middle_to_top_num_wire_ratio) + middle_to_top_num_wire_ratio; sub_phi_index++){ // phi rotation dd4hep::RotationZ rot_phi_top_wire((field_wires_top.phioffset + field_wires_top.phi * sub_phi_index) - phi_angle_sense_wire_rotation); - dd4hep::PlacedVolume field_wire_top_placedvolume = cellID_volume.placeVolume(field_wires_top.volume, dd4hep::Transform3D(rot_phi_top_wire * dd4hep::Translation3D(field_wires_top.radius, 0., 0.) * dd4hep::RotationX(field_wires_top.stereo - sense_wires.stereo))); + cellID_volume.placeVolume(field_wires_top.volume, dd4hep::Transform3D(rot_phi_top_wire * dd4hep::Translation3D(field_wires_top.radius, 0., 0.) * dd4hep::RotationX(field_wires_top.stereo - sense_wires.stereo))); + //dd4hep::PlacedVolume field_wire_top_placedvolume = cellID_volume.placeVolume(field_wires_top.volume, dd4hep::Transform3D(rot_phi_top_wire * dd4hep::Translation3D(field_wires_top.radius, 0., 0.) * dd4hep::RotationX(field_wires_top.stereo - sense_wires.stereo))); //if(setWireSensitive) // field_wire_top_placedvolume.addPhysVolID("phi", sub_phi_index).addPhysVolID("hitorigin", 2).addPhysVolID("stereo", field_wires_center.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 3); } @@ -771,7 +674,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_bottom.mother_volume = lvLayerVol.back(); field_wires_bottom.type = "F"; - field_wires_bottom.num = nFWire1; + field_wires_bottom.num = nFWireTopAndBottom; field_wires_bottom.radius = radius_layerIn_0 + FWradii + extShiftFW; field_wires_bottom.phi = 2. * TMath::Pi() / field_wires_bottom.num; field_wires_bottom.phioffset = layerangle + cellStaggering + phi_layer; @@ -787,7 +690,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti lvFwireVol.back().setVisAttributes(description, wirecol); field_wires_bottom.volume = lvFwireVol.back(); - CDCHBuild::PlaceWires(field_wires_bottom, FWireShellThickOut, halflength, SL, -1); + CDCHBuild::PlaceGuardWires(field_wires_bottom, FWireShellThickOut, halflength, SL, -1); //------------------------------------------------------------------------ // Start placing the outer layer of guard wires (#guard wires == # field wires) @@ -812,7 +715,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti guard_wires.mother_volume = lvLayerVol.back(); guard_wires.type = "G"; - guard_wires.num = nFWire1; + guard_wires.num = nFWireTopAndBottom; guard_wires.radius = outGuardRad - inGWradii; guard_wires.phi = 2. * TMath::Pi() / guard_wires.num; guard_wires.phioffset = layerangle; @@ -826,14 +729,14 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti lvGwireVol.back().setVisAttributes(description, wirecol); guard_wires.volume = lvGwireVol.back(); - CDCHBuild::PlaceWires(guard_wires, FWireShellThickOut, halflength, SL, -1); + CDCHBuild::PlaceGuardWires(guard_wires, FWireShellThickOut, halflength, SL, -1); guard_wires.volume = lvGwireVol.back(); // needed because applyWireCoating acts on it guard_wires.radius = outGuardRad + inGWradii + extShiftFW; guard_wires.phioffset = layerangle + phi_layer; guard_wires.stereo = -1.0 * epsilonOutGwRing; guard_wires.name = string("Gwire_outer_stereoplus"); - CDCHBuild::PlaceWires(guard_wires, FWireShellThickOut, halflength, SL, -1); + CDCHBuild::PlaceGuardWires(guard_wires, FWireShellThickOut, halflength, SL, -1); } } @@ -882,7 +785,7 @@ static dd4hep::Ref_t create_element(dd4hep::Detector& description, xml_h e, dd4h dd4hep::printout(dd4hep::DEBUG, "CreateCDCH", "Detector name: %s with ID: %s", det_name.c_str(), x_det.id()); DetElement CDCH_det = builder.detector; // ( det_name, x_det.id() ); - dd4hep::Tube CDCH_envelope(dd4hep::_toDouble("CDCH:r0"), dd4hep::_toDouble("CDCH:rOut"), dd4hep::_toDouble("CDCH:zHalfExtentWithServices")); + dd4hep::Tube CDCH_envelope(dd4hep::_toDouble("CDCH:inner_radius"), dd4hep::_toDouble("CDCH:outer_radius"), dd4hep::_toDouble("CDCH:zHalfExtentWithServices")); dd4hep::Volume envelope("lvCDCH", CDCH_envelope, description.air()); envelope.setVisAttributes(description, "vCDCH:Air"); From 0c10621082ce2efdcb6757fa09e71b90251c4374 Mon Sep 17 00:00:00 2001 From: BrieucF Date: Fri, 24 Nov 2023 14:32:05 +0100 Subject: [PATCH 13/29] [DriftChamber] More cleaning, commenting, variable renaming --- .../IDEA_o1_v02/DriftChamber_o1_v01.xml | 37 ++-- detector/tracker/DriftChamber_o1_v01.cpp | 158 +++++++++--------- 2 files changed, 103 insertions(+), 92 deletions(-) diff --git a/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml index dd58fc0fa..035f416e4 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml @@ -1,15 +1,15 @@ - Detector description for the IDEA Drift Chamber + 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 - + - + @@ -17,32 +17,36 @@ alpha = angle between the line (0,0,-zHalfLength) - (wireX,wireY,-zHalfLength) and the line (0,0,+zHalfLength) - (wireX,wireY,+zHalfLength) projected on the -zHalfLength plane perpandicular to z It is used to determine the radius of the hyperboloid in +- zHalfLength--> - - - - - - - - + + + + + + + + + - + - + - + - + - + + @@ -57,6 +61,7 @@ + diff --git a/detector/tracker/DriftChamber_o1_v01.cpp b/detector/tracker/DriftChamber_o1_v01.cpp index 5f83e30a0..0be10a9fb 100644 --- a/detector/tracker/DriftChamber_o1_v01.cpp +++ b/detector/tracker/DriftChamber_o1_v01.cpp @@ -18,15 +18,15 @@ using namespace dd4hep; struct wire { dd4hep::Volume mother_volume; - string type; - int num; - double radius; - double phi; - double phioffset; - double stereo; - double thickness; - double halflength; - dd4hep::Volume volume; + string type; // F = field wire, S = sense wire, G = guard wire + int num; // how many wires for the layer being considered + double radius; // radial position of the wire at z = 0 + double delta_phi; // delta phi between two wires of this type + double phioffset; // phi angle of the first wire of this type + double stereo; // stereo angle + double thickness; // thickness of the core of the wire (no coating) + double halflength; // wire z extent before stereo angle rotation + dd4hep::Volume volume; // actual volume of the wire string name; }; @@ -97,7 +97,7 @@ void CDCHBuild::PlaceGuardWires(struct wire& w, double outwrap, double halflengt // repeat the placement of wires over phi for (int n = 0; n < w.num; n++) { - dd4hep::RotationZ iRot(w.phioffset + w.phi * n); + dd4hep::RotationZ iRot(w.phioffset + w.delta_phi * n); if (n % 1 == 0) w.mother_volume.placeVolume(w.volume, dd4hep::Transform3D(iRot * T)); } } @@ -131,8 +131,8 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double SWireShellThickOut = dd4hep::_toDouble("CDCH:SWireShellThickOut"); double InGWireShellThickIn = dd4hep::_toDouble("CDCH:InGWireShellThickIn"); double InGWireShellThickOut = dd4hep::_toDouble("CDCH:InGWireShellThickOut"); - double OutGWireShellThickIn = dd4hep::_toDouble("CDCH:InGWireShellThickIn"); - //double OutGWireShellThickOut = dd4hep::_toDouble("CDCH:InGWireShellThickOut"); + double OutGWireShellThickIn = dd4hep::_toDouble("CDCH:OutGWireShellThickIn"); + double OutGWireShellThickOut = dd4hep::_toDouble("CDCH:OutGWireShellThickOut"); double secure = dd4hep::_toDouble("CDCH:secure"); double capGasLayer = dd4hep::_toDouble("CDCH:capGasLayer"); double extShiftFW = dd4hep::_toDouble("CDCH:extShiftFW"); @@ -141,23 +141,22 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double outGuardRad = dd4hep::_toDouble("CDCH:outGuardRad"); int nSDeltaWire = dd4hep::_toInt("CDCH:nSDeltaWire"); int nSWireFirstLayer = dd4hep::_toInt("CDCH:nSWireFirstLayer"); - int nStoFWireRatio = dd4hep::_toInt("CDCH:nStoFWireRatio"); - int nVerticalFWire = dd4hep::_toInt("CDCH:nVerticalFWire"); + int nFtoSWireRatio = dd4hep::_toInt("CDCH:nFtoSWireRatio"); + int nCenterFWirePerCell = dd4hep::_toInt("CDCH:nCenterFWirePerCell"); int nSuperLayer = dd4hep::_toInt("CDCH:nSuperLayer"); int nLayer = dd4hep::_toInt("CDCH:nLayer"); - //int nFieldWireShells = dd4hep::_toInt("CDCH:nFieldWireShells"); - //bool setWireSensitive = true; // FIXME: add the possibility to have wires sensitive (parameter in the xml) which could be useful for detailed chamber behavior studies, current attempt never lead to a hit in the wire, even with enlarged wires... + //bool setWireSensitive = true; // FIXME: add the possibility to have wires sensitive (parameter in the xml) which could be useful for detailed chamber behavior studies double halflength = zHalfExtentWithServices - (GasEndcapWallThick + CopperEndcapWallThick + KaptonEndcapWallThick + CarbonEndcapWallThick); // this will be the sensitive volume z extent double epsilon = 0.0; - double phi_layer = 0.0; - double phi_layer1 = 0.0; - int nFWire = 0; + double phi_offset = 0.0; + double delta_phi_top_bottom = 0.0; int nFWireTopAndBottom = 0; + int nFWireTopOrBottom = 0; int nSWire = 0; - int nHorizontalFWire = nStoFWireRatio - nVerticalFWire; + int nHorizontalFtoSWireRatio = nFtoSWireRatio - nCenterFWirePerCell; // nHorizontalFtoSWireRatio is, per cell, how many wires do we have in top and bottom layer (summed), knowing that the rightmost wires are not in the current cell int sign_epsilon = -1; - double cell_phi_coverage = 0.0; + double sense_wire_delta_phi = 0.0; double scaleFactor = 0.0; double dropFactor = 0.0; double epsilonFactor = 0.0; @@ -167,8 +166,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double idelta_radius = 0.0; double envelop_Inner_thickness = CarbonInnerWallThick + CopperInnerWallThick + GasInnerWallThick; - double envelop_Outer_thickness = - Carbon1OuterWallThick + Carbon2OuterWallThick + CopperOuterWallThick + FoamOuterWallThick; + double envelop_Outer_thickness = Carbon1OuterWallThick + Carbon2OuterWallThick + CopperOuterWallThick + FoamOuterWallThick; double FWireDiameter = FWireShellThickIn + FWireShellThickOut; double FWradii = 0.5 * FWireDiameter; //double SWireDiameter = SWireShellThickIn + SWireShellThickOut; @@ -188,7 +186,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double radius_layerOut = 0.0; double epsilonIn = 0.0; double epsilonOut = 0.0; - double layerangle = 0.0; + double phi_offset_cell_start = 0.0; //double cellBase = 0.0; double inscribedRadius = 0.0; //double circumscribedRadius = 0.0; @@ -200,10 +198,10 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double epsilonIn_whole_cell = 0.0; //------------------------------------------------------------------------ - // The enlarge parameter is used to see the wires in the rendering + // The enlarge parameter is used to see the wires in the rendering. NB: not propagated to the envelope volumes --> you will have volume extrusions if != 1 //------------------------------------------------------------------------ - double enlarge = 50.; + double enlarge = 10.; //------------------------------------------------------------------------ // Build the inner, outer and endcap walls first @@ -270,17 +268,17 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti for (int SL = 0; SL < nSuperLayer; ++SL) { nSWire = nSWireFirstLayer + SL * nSDeltaWire; - cell_phi_coverage = 2. * TMath::Pi() / nSWire; - nFWire = nHorizontalFWire * nSWire; - phi_layer = 2. * TMath::Pi() / nFWire; - nFWireTopAndBottom = nFWire / 2; - if (ceilf(nFWireTopAndBottom) != nFWireTopAndBottom) - throw std::runtime_error("Error: Failed to build CDCH. Please make sure that '(nStoFWireRatio - nVerticalFWire) * (nSWireFirstLayer + SuperLayerIndex * nSDeltaWire)' is always an even number"); - phi_layer1 = 2.0 * phi_layer; + sense_wire_delta_phi = 2. * TMath::Pi() / nSWire; + nFWireTopAndBottom = nHorizontalFtoSWireRatio * nSWire; + phi_offset = 2. * TMath::Pi() / nFWireTopAndBottom; + nFWireTopOrBottom = nFWireTopAndBottom / 2; + if (ceilf(nFWireTopOrBottom) != nFWireTopOrBottom) + throw std::runtime_error("Error: Failed to build CDCH. Please make sure that '(nFtoSWireRatio - nCenterFWirePerCell) * (nSWireFirstLayer + SuperLayerIndex * nSDeltaWire)' is always an even number"); + delta_phi_top_bottom = 2.0 * phi_offset; scaleFactor = (1.0 + TMath::Pi() / nSWire) / (1.0 - TMath::Pi() / nSWire); dropFactor = (1.0 / cos(halfalpha) - 1.0); // used to determine the radius of the hyperboloid in z = +- halflength with r_out = r_min + r_min * dropFactor epsilonFactor = sin(halfalpha) / halflength; - layerangle = -0.5 * cell_phi_coverage; + phi_offset_cell_start = -0.5 * sense_wire_delta_phi; gascol = "vCDCH:Gas1"; if (SL % 3 == 0) @@ -311,10 +309,10 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti guard_wires.mother_volume = lvLayerVol.back(); guard_wires.type = "G"; - guard_wires.num = nFWireTopAndBottom; //(#guard wires == # field wires) + guard_wires.num = nFWireTopOrBottom; //(#guard wires == # field wires) guard_wires.radius = inGuardRad - inGWradii; - guard_wires.phi = 2. * TMath::Pi() / guard_wires.num; - guard_wires.phioffset = layerangle; + guard_wires.delta_phi = 2. * TMath::Pi() / guard_wires.num; + guard_wires.phioffset = phi_offset_cell_start; guard_wires.stereo = epsilonInGwRing; guard_wires.thickness = 0.5 * InGWireShellThickIn * enlarge; // half the inner thickness as radius of tube guard_wires.halflength = zlength; @@ -329,7 +327,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti guard_wires.volume = lvGwireVol.back(); // needed because applyWireCoating acts on it guard_wires.radius = inGuardRad + inGWradii + extShiftFW; - guard_wires.phioffset = layerangle + phi_layer; + guard_wires.phioffset = phi_offset_cell_start + phi_offset; guard_wires.stereo = -1.0 * epsilonInGwRing; guard_wires.name = string("Gwire_inner_stereominus"); CDCHBuild::PlaceGuardWires(guard_wires, FWireShellThickOut, halflength, SL, -1); @@ -354,10 +352,10 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_top.mother_volume = lvLayerVol.back(); field_wires_top.type = "F"; - field_wires_top.num = nFWireTopAndBottom; + field_wires_top.num = nFWireTopOrBottom; field_wires_top.radius = radius_layerIn_0 - FWradii - extShiftFW; - field_wires_top.phi = 2. * TMath::Pi() /field_wires_top.num;; - field_wires_top.phioffset = layerangle + cellStaggering - phi_layer; + field_wires_top.delta_phi = 2. * TMath::Pi() /field_wires_top.num;; + field_wires_top.phioffset = phi_offset_cell_start + cellStaggering - phi_offset; field_wires_top.stereo = sign_epsilon * epsilon; field_wires_top.thickness = 0.5 * FWireShellThickIn * enlarge; field_wires_top.halflength = zlength; @@ -415,7 +413,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti zlength /= cos(epsilon); if (ilayer % 2 == 1) - cellStaggering = phi_layer; + cellStaggering = phi_offset; else cellStaggering = 0.0; @@ -425,10 +423,10 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti //------------------------------------------------------------------------ field_wires_bottom.type = "F"; - field_wires_bottom.num = nFWireTopAndBottom; + field_wires_bottom.num = nFWireTopOrBottom; field_wires_bottom.radius = radius_layerIn_0 + FWradii + extShiftFW; - field_wires_bottom.phi = phi_layer1; - field_wires_bottom.phioffset = layerangle + cellStaggering; + field_wires_bottom.delta_phi = delta_phi_top_bottom; + field_wires_bottom.phioffset = phi_offset_cell_start + cellStaggering; field_wires_bottom.stereo = sign_epsilon * epsilon; field_wires_bottom.thickness = 0.5 * FWireShellThickIn * enlarge; field_wires_bottom.halflength = zlength; @@ -474,6 +472,15 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti zlength -= sin(epsilon) * 0.5 * FWireShellThickIn; zlength /= cos(epsilon); + + ////------------------------------------------------------------------------ + //// Tune the radius and epsilon of the central field wires + ////------------------------------------------------------------------------ + + idelta_radius = delta_radius_layer * 0.5; + iradius += idelta_radius; + //epsilon = atan(iradius * (1.0 + dropFactor) * epsilonFactor); + //------------------------------------------------------------------------ // Fill the sense wire struct with all the relevant information //------------------------------------------------------------------------ @@ -481,7 +488,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti sense_wires.type = "S"; sense_wires.num = nSWire; sense_wires.radius = senseWireRing_radius_0; - sense_wires.phi = cell_phi_coverage; + sense_wires.delta_phi = sense_wire_delta_phi; sense_wires.phioffset = cellStaggering; sense_wires.stereo = sign_epsilon * epsilon; sense_wires.thickness = 0.5 * SWireShellThickIn * enlarge; @@ -500,23 +507,15 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti sense_wires.volume = lvSwireVol; apply_wire_coating(sense_wires, SWireShellThickOut, halflength, "G4_Au"); - //------------------------------------------------------------------------ - // Tune the radius and epsilon of the central field wires - //------------------------------------------------------------------------ - - idelta_radius = delta_radius_layer * 0.5; - iradius += idelta_radius; - epsilon = atan(iradius * (1.0 + dropFactor) * epsilonFactor); - //------------------------------------------------------------------------ // Fill the central field wire struct with all the relevant information //------------------------------------------------------------------------ field_wires_center.type = "F"; - field_wires_center.num = nSWire; - field_wires_center.radius = iradius; - field_wires_center.phi = cell_phi_coverage; - field_wires_center.phioffset = layerangle + cellStaggering; + field_wires_center.num = nSWire * nCenterFWirePerCell; + field_wires_center.radius = senseWireRing_radius_0; //iradius; + field_wires_center.delta_phi = 2. * TMath::Pi() / field_wires_center.num; + field_wires_center.phioffset = phi_offset_cell_start + cellStaggering; field_wires_center.stereo = sign_epsilon * epsilon; field_wires_center.thickness = 0.5 * centerFWireShellThickIn * enlarge; field_wires_center.halflength = zlength; @@ -524,6 +523,8 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_center.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(ilayer, "_layer%d") + string("_type") + field_wires_center.type + dd4hep::_toString(field_wires_center.stereo, "_stereo%f_center"); apply_wire_coating(field_wires_center, centerFWireShellThickOut, halflength); + // derive a phi offset to englobe the wires inside the sensitive volume (center field wires are the thickest) + //double phi_offset_to_englobe_wires = atan((field_wires_center.thickness + 0.5 * centerFWireShellThickOut) / field_wires_center.radius); //------------------------------------------------------------------------ // Next, fill the geometry parameters of the upper layer. @@ -562,10 +563,10 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti //------------------------------------------------------------------------ field_wires_top.type = "F"; - field_wires_top.num = nFWireTopAndBottom; + field_wires_top.num = nFWireTopOrBottom; field_wires_top.radius = radius_layerIn_0 - FWradii - extShiftFW; - field_wires_top.phi = phi_layer1; - field_wires_top.phioffset = layerangle + cellStaggering; + field_wires_top.delta_phi = delta_phi_top_bottom; + field_wires_top.phioffset = phi_offset_cell_start + cellStaggering; field_wires_top.stereo = sign_epsilon * epsilon; field_wires_top.thickness = 0.5 * FWireShellThickIn * enlarge; field_wires_top.halflength = zlength; @@ -580,8 +581,12 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // field_wires_top.volume.setSensitiveDetector(sens_det); //} - // Create the tube segment volume to identify the cell sensitive regions (FIXME could be improved with e.g. extruded valumes or tessalatedSolids) - dd4hep::Tube cellID_tube_segment(radius_layerIn_whole_cell, radius_layerOut_0, halflength, - sense_wires.phi / 2.0, sense_wires.phi / 2.0); + // Create the tube segment volume to identify the cell sensitive regions + // FIXME: this leads to some volume extrusion (corner of the tube going outside of the hyperboloid mother volume) + // Using the intersection with the hyperboloid mother volume solves it but severely impacts the perfomance (memory and CPU) of the geometry building + // Other paths to investigate are twisted tubes (caveat: no TGeo shape equivalent), extruded volumes or tessalated solids + //dd4hep::Tube cellID_tube_segment(radius_layerIn_whole_cell, radius_layerOut_0, halflength, (- sense_wires.delta_phi / 2.0) - phi_offset_to_englobe_wires, (sense_wires.delta_phi / 2.0) - phi_offset_to_englobe_wires); + dd4hep::Tube cellID_tube_segment(radius_layerIn_whole_cell, radius_layerOut_0, halflength, - sense_wires.delta_phi / 2.0, sense_wires.delta_phi / 2.0); // Radial translation dd4hep::Translation3D radial_translation_sense_wire(sense_wires.radius, 0., 0.); @@ -601,7 +606,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti dd4hep::Volume cellID_volume = dd4hep::Volume(cellID_volume_name, cellID_tube_segment, description.material("GasHe_90Isob_10")); cellID_volume.setSensitiveDetector(sens_det); // phi rotation - double phi_angle_sense_wire_rotation = sense_wires.phioffset + sense_wires.phi * phi_index; + double phi_angle_sense_wire_rotation = sense_wires.phioffset + sense_wires.delta_phi * phi_index; dd4hep::RotationZ rot_phi_sense_wire(phi_angle_sense_wire_rotation); dd4hep::PlacedVolume cellID_placedvolume = whole_layer_hyperboloid_volume.placeVolume(cellID_volume, dd4hep::Transform3D(rot_phi_sense_wire * rot_stereo_sense_wire)); cellID_placedvolume.addPhysVolID("phi", phi_index).addPhysVolID("hitorigin", 0).addPhysVolID("stereo", sense_wires.stereo > 0 ? 0 : 1).addPhysVolID("layerInCell", 0); @@ -619,7 +624,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // bottom field wires for(int sub_phi_index = phi_index * middle_to_bottom_num_wire_ratio; sub_phi_index < (phi_index * middle_to_bottom_num_wire_ratio) + middle_to_bottom_num_wire_ratio; sub_phi_index++){ // phi rotation - dd4hep::RotationZ rot_phi_bottom_wire((field_wires_bottom.phioffset + field_wires_bottom.phi * sub_phi_index) - phi_angle_sense_wire_rotation); + dd4hep::RotationZ rot_phi_bottom_wire((field_wires_bottom.phioffset + field_wires_bottom.delta_phi * sub_phi_index) - phi_angle_sense_wire_rotation); cellID_volume.placeVolume(field_wires_bottom.volume, dd4hep::Transform3D(rot_phi_bottom_wire * dd4hep::Translation3D(field_wires_bottom.radius, 0., 0.) * dd4hep::RotationX(field_wires_bottom.stereo - sense_wires.stereo))); //dd4hep::PlacedVolume field_wire_bottom_placedvolume = cellID_volume.placeVolume(field_wires_bottom.volume, dd4hep::Transform3D(rot_phi_bottom_wire * dd4hep::Translation3D(field_wires_bottom.radius, 0., 0.) * dd4hep::RotationX(field_wires_bottom.stereo - sense_wires.stereo))); //if(setWireSensitive) @@ -629,7 +634,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // central field wires for(int sub_phi_index = phi_index * middle_to_middle_num_wire_ratio; sub_phi_index < (phi_index * middle_to_middle_num_wire_ratio) + middle_to_middle_num_wire_ratio; sub_phi_index++){ // phi rotation - dd4hep::RotationZ rot_phi_center_wire((field_wires_center.phioffset + field_wires_center.phi * sub_phi_index) - phi_angle_sense_wire_rotation); + dd4hep::RotationZ rot_phi_center_wire((field_wires_center.phioffset + field_wires_center.delta_phi * sub_phi_index) - phi_angle_sense_wire_rotation); cellID_volume.placeVolume(field_wires_center.volume, dd4hep::Transform3D(rot_phi_center_wire * dd4hep::Translation3D(field_wires_center.radius, 0., 0.) * dd4hep::RotationX(field_wires_center.stereo - sense_wires.stereo))); //dd4hep::PlacedVolume field_wire_center_placedvolume = cellID_volume.placeVolume(field_wires_center.volume, dd4hep::Transform3D(rot_phi_center_wire * dd4hep::Translation3D(field_wires_center.radius, 0., 0.) * dd4hep::RotationX(field_wires_center.stereo - sense_wires.stereo))); //if(setWireSensitive) @@ -639,7 +644,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // top field wires for(int sub_phi_index = phi_index * middle_to_top_num_wire_ratio; sub_phi_index < (phi_index * middle_to_top_num_wire_ratio) + middle_to_top_num_wire_ratio; sub_phi_index++){ // phi rotation - dd4hep::RotationZ rot_phi_top_wire((field_wires_top.phioffset + field_wires_top.phi * sub_phi_index) - phi_angle_sense_wire_rotation); + dd4hep::RotationZ rot_phi_top_wire((field_wires_top.phioffset + field_wires_top.delta_phi * sub_phi_index) - phi_angle_sense_wire_rotation); cellID_volume.placeVolume(field_wires_top.volume, dd4hep::Transform3D(rot_phi_top_wire * dd4hep::Translation3D(field_wires_top.radius, 0., 0.) * dd4hep::RotationX(field_wires_top.stereo - sense_wires.stereo))); //dd4hep::PlacedVolume field_wire_top_placedvolume = cellID_volume.placeVolume(field_wires_top.volume, dd4hep::Transform3D(rot_phi_top_wire * dd4hep::Translation3D(field_wires_top.radius, 0., 0.) * dd4hep::RotationX(field_wires_top.stereo - sense_wires.stereo))); //if(setWireSensitive) @@ -652,6 +657,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti //------------------------------------------------------------------------ delta_radius_layer *= scaleFactor; + epsilon = atan(iradius * (1.0 + dropFactor) * epsilonFactor); // FIXME the stereo angle is here assumed to be constant for a given cell while it should be different for the bottom, middle and top rings of the cell } if (SL == (nSuperLayer - 1)) {// the last super layer is special since we need to add the field wires outside of the sensitive volume and the guard wires @@ -674,10 +680,10 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_bottom.mother_volume = lvLayerVol.back(); field_wires_bottom.type = "F"; - field_wires_bottom.num = nFWireTopAndBottom; + field_wires_bottom.num = nFWireTopOrBottom; field_wires_bottom.radius = radius_layerIn_0 + FWradii + extShiftFW; - field_wires_bottom.phi = 2. * TMath::Pi() / field_wires_bottom.num; - field_wires_bottom.phioffset = layerangle + cellStaggering + phi_layer; + field_wires_bottom.delta_phi = 2. * TMath::Pi() / field_wires_bottom.num; + field_wires_bottom.phioffset = phi_offset_cell_start + cellStaggering + phi_offset; field_wires_bottom.stereo = -1. * sign_epsilon * epsilon; field_wires_bottom.thickness = 0.5 * FWireShellThickIn * enlarge; field_wires_bottom.halflength = zlength; @@ -715,10 +721,10 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti guard_wires.mother_volume = lvLayerVol.back(); guard_wires.type = "G"; - guard_wires.num = nFWireTopAndBottom; + guard_wires.num = nFWireTopOrBottom; guard_wires.radius = outGuardRad - inGWradii; - guard_wires.phi = 2. * TMath::Pi() / guard_wires.num; - guard_wires.phioffset = layerangle; + guard_wires.delta_phi = 2. * TMath::Pi() / guard_wires.num; + guard_wires.phioffset = phi_offset_cell_start; guard_wires.stereo = epsilonOutGwRing; guard_wires.thickness = 0.5 * OutGWireShellThickIn * enlarge; guard_wires.halflength = zlength; @@ -729,14 +735,14 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti lvGwireVol.back().setVisAttributes(description, wirecol); guard_wires.volume = lvGwireVol.back(); - CDCHBuild::PlaceGuardWires(guard_wires, FWireShellThickOut, halflength, SL, -1); + CDCHBuild::PlaceGuardWires(guard_wires, OutGWireShellThickOut, halflength, SL, -1); guard_wires.volume = lvGwireVol.back(); // needed because applyWireCoating acts on it guard_wires.radius = outGuardRad + inGWradii + extShiftFW; - guard_wires.phioffset = layerangle + phi_layer; + guard_wires.phioffset = phi_offset_cell_start + phi_offset; guard_wires.stereo = -1.0 * epsilonOutGwRing; guard_wires.name = string("Gwire_outer_stereoplus"); - CDCHBuild::PlaceGuardWires(guard_wires, FWireShellThickOut, halflength, SL, -1); + CDCHBuild::PlaceGuardWires(guard_wires, OutGWireShellThickOut, halflength, SL, -1); } } From 872fdedda13f54c644443aa5954183f2b5159362 Mon Sep 17 00:00:00 2001 From: BrieucF Date: Fri, 24 Nov 2023 14:35:33 +0100 Subject: [PATCH 14/29] [DriftChamber] Fix volume extrusion: englobe 'left' (clockwise) wires in the cell volume --- detector/tracker/DriftChamber_o1_v01.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/detector/tracker/DriftChamber_o1_v01.cpp b/detector/tracker/DriftChamber_o1_v01.cpp index 0be10a9fb..df4f6c063 100644 --- a/detector/tracker/DriftChamber_o1_v01.cpp +++ b/detector/tracker/DriftChamber_o1_v01.cpp @@ -524,7 +524,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti apply_wire_coating(field_wires_center, centerFWireShellThickOut, halflength); // derive a phi offset to englobe the wires inside the sensitive volume (center field wires are the thickest) - //double phi_offset_to_englobe_wires = atan((field_wires_center.thickness + 0.5 * centerFWireShellThickOut) / field_wires_center.radius); + double phi_offset_to_englobe_wires = atan((field_wires_center.thickness + 0.5 * centerFWireShellThickOut) / field_wires_center.radius); //------------------------------------------------------------------------ // Next, fill the geometry parameters of the upper layer. @@ -585,8 +585,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // FIXME: this leads to some volume extrusion (corner of the tube going outside of the hyperboloid mother volume) // Using the intersection with the hyperboloid mother volume solves it but severely impacts the perfomance (memory and CPU) of the geometry building // Other paths to investigate are twisted tubes (caveat: no TGeo shape equivalent), extruded volumes or tessalated solids - //dd4hep::Tube cellID_tube_segment(radius_layerIn_whole_cell, radius_layerOut_0, halflength, (- sense_wires.delta_phi / 2.0) - phi_offset_to_englobe_wires, (sense_wires.delta_phi / 2.0) - phi_offset_to_englobe_wires); - dd4hep::Tube cellID_tube_segment(radius_layerIn_whole_cell, radius_layerOut_0, halflength, - sense_wires.delta_phi / 2.0, sense_wires.delta_phi / 2.0); + dd4hep::Tube cellID_tube_segment(radius_layerIn_whole_cell, radius_layerOut_0, halflength, (- sense_wires.delta_phi / 2.0) - phi_offset_to_englobe_wires, (sense_wires.delta_phi / 2.0) - phi_offset_to_englobe_wires); // Radial translation dd4hep::Translation3D radial_translation_sense_wire(sense_wires.radius, 0., 0.); From e14651d20127404d5fe2469b78fc848561cfc4de Mon Sep 17 00:00:00 2001 From: BrieucF Date: Fri, 24 Nov 2023 16:31:45 +0100 Subject: [PATCH 15/29] [DriftChamber] Fix wire protrusion from hyperboloid --- detector/tracker/DriftChamber_o1_v01.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/detector/tracker/DriftChamber_o1_v01.cpp b/detector/tracker/DriftChamber_o1_v01.cpp index df4f6c063..9e4e5c04c 100644 --- a/detector/tracker/DriftChamber_o1_v01.cpp +++ b/detector/tracker/DriftChamber_o1_v01.cpp @@ -523,7 +523,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_center.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(ilayer, "_layer%d") + string("_type") + field_wires_center.type + dd4hep::_toString(field_wires_center.stereo, "_stereo%f_center"); apply_wire_coating(field_wires_center, centerFWireShellThickOut, halflength); - // derive a phi offset to englobe the wires inside the sensitive volume (center field wires are the thickest) + // derive a phi offset to englobe the 'left' (clockwise) wires inside the sensitive volume (center field wires are the thickest) double phi_offset_to_englobe_wires = atan((field_wires_center.thickness + 0.5 * centerFWireShellThickOut) / field_wires_center.radius); //------------------------------------------------------------------------ @@ -540,7 +540,9 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // Create hyperboloid volume of the whole layer for the cell sensitive volume definition, not needed per se but helps having a well balanced volume tree (having too many volumes inside one mother volume harms performance) wholeHyperboloidVolumeName = dd4hep::_toString(SL, "hyperboloid_SL_%d") + dd4hep::_toString(ilayer, "_layer_%d"); - dd4hep::Hyperboloid whole_layer_hyperboloid = dd4hep::Hyperboloid(radius_layerIn_whole_cell, epsilonIn_whole_cell, radius_layerOut_0, epsilonOut, zlength); + double radial_inner_offset_to_englobe_wires = field_wires_bottom.thickness + 0.5 * FWireShellThickOut; + double radial_outer_offset_to_englobe_wires = field_wires_top.thickness + 0.5 * FWireShellThickOut; + dd4hep::Hyperboloid whole_layer_hyperboloid = dd4hep::Hyperboloid(radius_layerIn_whole_cell - radial_inner_offset_to_englobe_wires, epsilonIn_whole_cell, radius_layerOut_0 + radial_outer_offset_to_englobe_wires, epsilonOut, zlength); dd4hep::Volume whole_layer_hyperboloid_volume = dd4hep::Volume(wholeHyperboloidVolumeName, whole_layer_hyperboloid, description.material("GasHe_90Isob_10")); whole_layer_hyperboloid_volume.setVisAttributes(description, gascol); //registerVolume(wholeHyperboloidVolumeName, whole_layer_hyperboloid_volume); From 090005aaf8d7d11f389a58c62a8c21810896a318 Mon Sep 17 00:00:00 2001 From: BrieucF Date: Tue, 5 Dec 2023 16:34:16 +0100 Subject: [PATCH 16/29] [DriftChamber] More commenting/renaming --- detector/tracker/DriftChamber_o1_v01.cpp | 125 +++++++++++------------ 1 file changed, 59 insertions(+), 66 deletions(-) diff --git a/detector/tracker/DriftChamber_o1_v01.cpp b/detector/tracker/DriftChamber_o1_v01.cpp index 9e4e5c04c..f16c46470 100644 --- a/detector/tracker/DriftChamber_o1_v01.cpp +++ b/detector/tracker/DriftChamber_o1_v01.cpp @@ -161,7 +161,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double dropFactor = 0.0; double epsilonFactor = 0.0; double delta_radius_layer = cellDimension; - double senseWireRing_radius_0 = 0.0; + double sense_wire_radius_at_z_0 = 0.0; double iradius = 0.0; double idelta_radius = 0.0; @@ -169,32 +169,27 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double envelop_Outer_thickness = Carbon1OuterWallThick + Carbon2OuterWallThick + CopperOuterWallThick + FoamOuterWallThick; double FWireDiameter = FWireShellThickIn + FWireShellThickOut; double FWradii = 0.5 * FWireDiameter; - //double SWireDiameter = SWireShellThickIn + SWireShellThickOut; - //double SWradii = 0.5 * SWireDiameter; double inGWireDiameter = InGWireShellThickIn + InGWireShellThickOut; double inGWradii = 0.5 * inGWireDiameter; double fakeLayerInIWthick = -0.0001 + GasInnerWallThick; - double inner_radius_0 = inner_radius + envelop_Inner_thickness - fakeLayerInIWthick; + double guard_layer_inner_radius_at_z_0 = inner_radius + envelop_Inner_thickness - fakeLayerInIWthick; double radius_layer_0 = inner_radius + envelop_Inner_thickness + FWradii + secure + capGasLayer; - double radius_layerOut_0 = radius_layer_0 - FWradii - secure; + double layer_outer_radius_at_z_0 = radius_layer_0 - FWradii - secure; double drop = 0.0; double radius_layer = 0.0; - double radius_layerIn_0 = 0.0; - double radius_layerIn = 0.0; - double radius_layerOut = 0.0; + double layer_inner_radius_at_z_0 = 0.0; + double layer_inner_radius_at_z_end = 0.0; + double layer_outer_radius_at_z_end = 0.0; double epsilonIn = 0.0; double epsilonOut = 0.0; double phi_offset_cell_start = 0.0; - //double cellBase = 0.0; - double inscribedRadius = 0.0; - //double circumscribedRadius = 0.0; double zlength = 0.0; double cellStaggering = 0.0; double epsilonInGwRing = 0.0; double epsilonOutGwRing = 0.0; - double radius_layerIn_whole_cell = 0.0; + double layer_inner_radius_at_z_end_whole_cell = 0.0; double epsilonIn_whole_cell = 0.0; //------------------------------------------------------------------------ @@ -275,7 +270,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti if (ceilf(nFWireTopOrBottom) != nFWireTopOrBottom) throw std::runtime_error("Error: Failed to build CDCH. Please make sure that '(nFtoSWireRatio - nCenterFWirePerCell) * (nSWireFirstLayer + SuperLayerIndex * nSDeltaWire)' is always an even number"); delta_phi_top_bottom = 2.0 * phi_offset; - scaleFactor = (1.0 + TMath::Pi() / nSWire) / (1.0 - TMath::Pi() / nSWire); + scaleFactor = (1.0 + TMath::Pi() / nSWire) / (1.0 - TMath::Pi() / nSWire); // used to scale the radial extent of each layer which grows towards outer radius dropFactor = (1.0 / cos(halfalpha) - 1.0); // used to determine the radius of the hyperboloid in z = +- halflength with r_out = r_min + r_min * dropFactor epsilonFactor = sin(halfalpha) / halflength; phi_offset_cell_start = -0.5 * sense_wire_delta_phi; @@ -298,7 +293,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti if (SL == 0) {// SL = 0 is special due to the guard wires and the first field wires that lie outside of the sensitive volume double stereoOut0 = atan(sqrt(diff_of_squares((inGuardRad - inGWradii) + (inGuardRad - inGWradii) * dropFactor, inGuardRad - inGWradii)) / halflength); - dd4hep::Hyperboloid HypeLayer0(inner_radius_0, 0.0, radius_layerOut_0 - secure, stereoOut0, halflength); + dd4hep::Hyperboloid HypeLayer0(guard_layer_inner_radius_at_z_0, 0.0, layer_outer_radius_at_z_0 - secure, stereoOut0, halflength); lvLayerVol.push_back(dd4hep::Volume("hyperboloid_inner_guard_layer", HypeLayer0, description.material("GasHe_90Isob_10"))); lvLayerVol.back().setVisAttributes(description, "vCDCH:Pb"); @@ -335,31 +330,32 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti drop = radius_layer_0 * dropFactor; radius_layer = radius_layer_0 + drop; epsilon = atan(radius_layer * epsilonFactor); - radius_layerIn_0 = radius_layer_0 - FWradii - 2.0 * secure; - radius_layerIn = radius_layerIn_0 + drop; - radius_layerOut_0 = radius_layer_0 + FWradii; - radius_layerOut = radius_layerOut_0 + drop; - epsilonIn = atan(sqrt(pow(radius_layerIn, 2) - pow(radius_layerIn_0, 2)) / halflength); - epsilonOut = atan(sqrt(pow(radius_layerOut, 2) - pow(radius_layerOut_0, 2)) / halflength); - - dd4hep::Hyperboloid HypeLayer1(radius_layerIn_0, epsilonIn, radius_layerOut_0, epsilonOut, halflength); - lvLayerVol.push_back(dd4hep::Volume("hyperboloid_first_field_wire_ring", HypeLayer1, description.material("GasHe_90Isob_10"))); - lvLayerVol.back().setVisAttributes(description, "vCDCH:Plastic"); + layer_inner_radius_at_z_0 = radius_layer_0 - FWradii - 2.0 * secure; + layer_inner_radius_at_z_end = layer_inner_radius_at_z_0 + drop; + layer_outer_radius_at_z_0 = radius_layer_0 + FWradii; + layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; + epsilonIn = atan(sqrt(pow(layer_inner_radius_at_z_end, 2) - pow(layer_inner_radius_at_z_0, 2)) / halflength); + epsilonOut = atan(sqrt(pow(layer_outer_radius_at_z_end, 2) - pow(layer_outer_radius_at_z_0, 2)) / halflength); + zlength = halflength; zlength -= sin(epsilon) * FWradii; zlength /= cos(epsilon); - field_wires_top.mother_volume = lvLayerVol.back(); field_wires_top.type = "F"; field_wires_top.num = nFWireTopOrBottom; - field_wires_top.radius = radius_layerIn_0 - FWradii - extShiftFW; + field_wires_top.radius = layer_inner_radius_at_z_0 - FWradii - extShiftFW; field_wires_top.delta_phi = 2. * TMath::Pi() /field_wires_top.num;; field_wires_top.phioffset = phi_offset_cell_start + cellStaggering - phi_offset; field_wires_top.stereo = sign_epsilon * epsilon; field_wires_top.thickness = 0.5 * FWireShellThickIn * enlarge; field_wires_top.halflength = zlength; + dd4hep::Hyperboloid HypeLayer1(layer_inner_radius_at_z_0, epsilonIn, layer_outer_radius_at_z_0 + field_wires_top.thickness + 0.5 * FWireShellThickOut, epsilonOut, halflength); + lvLayerVol.push_back(dd4hep::Volume("hyperboloid_first_field_wire_ring", HypeLayer1, description.material("GasHe_90Isob_10"))); + lvLayerVol.back().setVisAttributes(description, "vCDCH:Plastic"); + field_wires_top.mother_volume = lvLayerVol.back(); + lvFwireName = dd4hep::_toString(SL, "lvFwire_%d_init"); field_wires_top.name = string(lvFwireName); @@ -373,7 +369,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti radius_layer_0 += FWradii; } else { - delta_radius_layer = 2. * TMath::Pi() * radius_layerOut_0 / (nSWire - TMath::Pi()); + delta_radius_layer = 2. * TMath::Pi() * layer_outer_radius_at_z_0 / (nSWire - TMath::Pi()); } //------------------------------------------------------------------------ @@ -386,23 +382,21 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // on top of the following one, so new layerIn = old layerOut //------------------------------------------------------------------------ - inscribedRadius = 0.5 * delta_radius_layer; - //circumscribedRadius = inscribedRadius * sqrt(2.0); - senseWireRing_radius_0 = radius_layer_0 + inscribedRadius; + sense_wire_radius_at_z_0 = radius_layer_0 + 0.5 * delta_radius_layer; sign_epsilon *= -1; - radius_layerIn_0 = radius_layerOut_0; - radius_layerIn = radius_layerOut; + layer_inner_radius_at_z_0 = layer_outer_radius_at_z_0; + layer_inner_radius_at_z_end = layer_outer_radius_at_z_end; epsilonIn = epsilonOut; - radius_layerOut_0 = radius_layerIn_0 + FWireDiameter + 2.0 * secure; - radius_layerOut = radius_layerOut_0 + drop; - epsilonOut = atan(sqrt(diff_of_squares(radius_layerOut, radius_layerOut_0)) / halflength); + layer_outer_radius_at_z_0 = layer_inner_radius_at_z_0 + FWireDiameter + 2.0 * secure; + layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; + epsilonOut = atan(sqrt(diff_of_squares(layer_outer_radius_at_z_end, layer_outer_radius_at_z_0)) / halflength); zlength = halflength; // save bottom layer inner radius and epsilon before they are modified to build the whole layer hyperboloid volume - radius_layerIn_whole_cell = radius_layerIn_0; + layer_inner_radius_at_z_end_whole_cell = layer_inner_radius_at_z_0; epsilonIn_whole_cell = epsilonIn; //------------------------------------------------------------------------ @@ -424,7 +418,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_bottom.type = "F"; field_wires_bottom.num = nFWireTopOrBottom; - field_wires_bottom.radius = radius_layerIn_0 + FWradii + extShiftFW; + field_wires_bottom.radius = layer_inner_radius_at_z_0 + FWradii + extShiftFW; field_wires_bottom.delta_phi = delta_phi_top_bottom; field_wires_bottom.phioffset = phi_offset_cell_start + cellStaggering; field_wires_bottom.stereo = sign_epsilon * epsilon; @@ -457,12 +451,12 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti radius_layer_0 += delta_radius_layer; drop = radius_layer_0 * dropFactor; - radius_layerIn_0 = radius_layerOut_0; - radius_layerIn = radius_layerOut; + layer_inner_radius_at_z_0 = layer_outer_radius_at_z_0; + layer_inner_radius_at_z_end = layer_outer_radius_at_z_end; epsilonIn = epsilonOut; - radius_layerOut_0 = radius_layer_0 - FWireDiameter - 2.0 * secure; - radius_layerOut = radius_layerOut_0 + drop; - epsilonOut = atan(sqrt(diff_of_squares(radius_layerOut, radius_layerOut_0)) / halflength); + layer_outer_radius_at_z_0 = radius_layer_0 - FWireDiameter - 2.0 * secure; + layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; + epsilonOut = atan(sqrt(diff_of_squares(layer_outer_radius_at_z_end, layer_outer_radius_at_z_0)) / halflength); zlength = halflength; //------------------------------------------------------------------------ @@ -487,7 +481,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti sense_wires.type = "S"; sense_wires.num = nSWire; - sense_wires.radius = senseWireRing_radius_0; + sense_wires.radius = sense_wire_radius_at_z_0; sense_wires.delta_phi = sense_wire_delta_phi; sense_wires.phioffset = cellStaggering; sense_wires.stereo = sign_epsilon * epsilon; @@ -513,7 +507,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_center.type = "F"; field_wires_center.num = nSWire * nCenterFWirePerCell; - field_wires_center.radius = senseWireRing_radius_0; //iradius; + field_wires_center.radius = sense_wire_radius_at_z_0; //iradius; field_wires_center.delta_phi = 2. * TMath::Pi() / field_wires_center.num; field_wires_center.phioffset = phi_offset_cell_start + cellStaggering; field_wires_center.stereo = sign_epsilon * epsilon; @@ -530,19 +524,19 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // Next, fill the geometry parameters of the upper layer. //------------------------------------------------------------------------ - radius_layerIn_0 = radius_layerOut_0; - radius_layerIn = radius_layerOut; + layer_inner_radius_at_z_0 = layer_outer_radius_at_z_0; + layer_inner_radius_at_z_end = layer_outer_radius_at_z_end; epsilonIn = epsilonOut; - radius_layerOut_0 = radius_layerIn_0 + FWireDiameter + 2.0 * secure; - radius_layerOut = radius_layerOut_0 + drop; - epsilonOut = atan(sqrt(diff_of_squares(radius_layerOut, radius_layerOut_0)) / halflength); + layer_outer_radius_at_z_0 = layer_inner_radius_at_z_0 + FWireDiameter + 2.0 * secure; + layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; + epsilonOut = atan(sqrt(diff_of_squares(layer_outer_radius_at_z_end, layer_outer_radius_at_z_0)) / halflength); zlength = halflength; // Create hyperboloid volume of the whole layer for the cell sensitive volume definition, not needed per se but helps having a well balanced volume tree (having too many volumes inside one mother volume harms performance) wholeHyperboloidVolumeName = dd4hep::_toString(SL, "hyperboloid_SL_%d") + dd4hep::_toString(ilayer, "_layer_%d"); double radial_inner_offset_to_englobe_wires = field_wires_bottom.thickness + 0.5 * FWireShellThickOut; double radial_outer_offset_to_englobe_wires = field_wires_top.thickness + 0.5 * FWireShellThickOut; - dd4hep::Hyperboloid whole_layer_hyperboloid = dd4hep::Hyperboloid(radius_layerIn_whole_cell - radial_inner_offset_to_englobe_wires, epsilonIn_whole_cell, radius_layerOut_0 + radial_outer_offset_to_englobe_wires, epsilonOut, zlength); + dd4hep::Hyperboloid whole_layer_hyperboloid = dd4hep::Hyperboloid(layer_inner_radius_at_z_end_whole_cell - radial_inner_offset_to_englobe_wires, epsilonIn_whole_cell, layer_outer_radius_at_z_0 + radial_outer_offset_to_englobe_wires, epsilonOut, zlength); dd4hep::Volume whole_layer_hyperboloid_volume = dd4hep::Volume(wholeHyperboloidVolumeName, whole_layer_hyperboloid, description.material("GasHe_90Isob_10")); whole_layer_hyperboloid_volume.setVisAttributes(description, gascol); //registerVolume(wholeHyperboloidVolumeName, whole_layer_hyperboloid_volume); @@ -566,7 +560,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_top.type = "F"; field_wires_top.num = nFWireTopOrBottom; - field_wires_top.radius = radius_layerIn_0 - FWradii - extShiftFW; + field_wires_top.radius = layer_inner_radius_at_z_0 - FWradii - extShiftFW; field_wires_top.delta_phi = delta_phi_top_bottom; field_wires_top.phioffset = phi_offset_cell_start + cellStaggering; field_wires_top.stereo = sign_epsilon * epsilon; @@ -587,7 +581,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // FIXME: this leads to some volume extrusion (corner of the tube going outside of the hyperboloid mother volume) // Using the intersection with the hyperboloid mother volume solves it but severely impacts the perfomance (memory and CPU) of the geometry building // Other paths to investigate are twisted tubes (caveat: no TGeo shape equivalent), extruded volumes or tessalated solids - dd4hep::Tube cellID_tube_segment(radius_layerIn_whole_cell, radius_layerOut_0, halflength, (- sense_wires.delta_phi / 2.0) - phi_offset_to_englobe_wires, (sense_wires.delta_phi / 2.0) - phi_offset_to_englobe_wires); + dd4hep::Tube cellID_tube_segment(layer_inner_radius_at_z_end_whole_cell - radial_inner_offset_to_englobe_wires, layer_outer_radius_at_z_0 + radial_outer_offset_to_englobe_wires, halflength, (- sense_wires.delta_phi / 2.0) - phi_offset_to_englobe_wires, (sense_wires.delta_phi / 2.0) - phi_offset_to_englobe_wires); // Radial translation dd4hep::Translation3D radial_translation_sense_wire(sense_wires.radius, 0., 0.); @@ -664,14 +658,14 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti if (SL == (nSuperLayer - 1)) {// the last super layer is special since we need to add the field wires outside of the sensitive volume and the guard wires // Take care of the field wires outside of the sensitive volume - radius_layerIn_0 = radius_layerOut_0; - radius_layerIn = radius_layerOut; + layer_inner_radius_at_z_0 = layer_outer_radius_at_z_0; + layer_inner_radius_at_z_end = layer_outer_radius_at_z_end; epsilonIn = epsilonOut; - radius_layerOut_0 = radius_layer_0 + FWireDiameter + 2.0 * secure; - radius_layerOut = radius_layerOut_0 + drop; - epsilonOut = atan(sqrt(diff_of_squares(radius_layerOut, radius_layerOut_0)) / halflength); + layer_outer_radius_at_z_0 = radius_layer_0 + FWireDiameter + 2.0 * secure; + layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; + epsilonOut = atan(sqrt(diff_of_squares(layer_outer_radius_at_z_end, layer_outer_radius_at_z_0)) / halflength); - dd4hep::Hyperboloid HypeLayerOut(radius_layerIn_0, epsilonIn, radius_layerOut_0, epsilonOut, halflength); + dd4hep::Hyperboloid HypeLayerOut(layer_inner_radius_at_z_0, epsilonIn, layer_outer_radius_at_z_0, epsilonOut, halflength); lvLayerVol.push_back(dd4hep::Volume("hyperboloid_last_field_wire_ring", HypeLayerOut, description.material("GasHe_90Isob_10"))); lvLayerVol.back().setVisAttributes(description, "vCDCH:Plastic"); @@ -682,7 +676,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_bottom.mother_volume = lvLayerVol.back(); field_wires_bottom.type = "F"; field_wires_bottom.num = nFWireTopOrBottom; - field_wires_bottom.radius = radius_layerIn_0 + FWradii + extShiftFW; + field_wires_bottom.radius = layer_inner_radius_at_z_0 + FWradii + extShiftFW; field_wires_bottom.delta_phi = 2. * TMath::Pi() / field_wires_bottom.num; field_wires_bottom.phioffset = phi_offset_cell_start + cellStaggering + phi_offset; field_wires_bottom.stereo = -1. * sign_epsilon * epsilon; @@ -703,14 +697,14 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // Start placing the outer layer of guard wires (#guard wires == # field wires) //------------------------------------------------------------------------ - radius_layerIn_0 = radius_layerOut_0; - radius_layerIn = radius_layerOut; + layer_inner_radius_at_z_0 = layer_outer_radius_at_z_0; + layer_inner_radius_at_z_end = layer_outer_radius_at_z_end; epsilonIn = epsilonOut; - radius_layerOut_0 = radius_layer_0 + FWireDiameter + 2.0 * secure; - radius_layerOut = radius_layerOut_0 + drop; - epsilonOut = atan(sqrt(diff_of_squares(radius_layerOut, radius_layerOut_0)) / halflength); + layer_outer_radius_at_z_0 = radius_layer_0 + FWireDiameter + 2.0 * secure; + layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; + epsilonOut = atan(sqrt(diff_of_squares(layer_outer_radius_at_z_end, layer_outer_radius_at_z_0)) / halflength); - dd4hep::Hyperboloid HypeLayerOutG(radius_layerIn_0, epsilonOut, outer_radius - envelop_Outer_thickness - 0.0001, + dd4hep::Hyperboloid HypeLayerOutG(layer_inner_radius_at_z_0, epsilonOut, outer_radius - envelop_Outer_thickness - 0.0001, 0.0, halflength); lvLayerVol.push_back(dd4hep::Volume("hyperboloid_outer_guard_layer", HypeLayerOutG, description.material("GasHe_90Isob_10"))); lvLayerVol.back().setVisAttributes(description, "vCDCH:Pb"); @@ -834,4 +828,3 @@ static dd4hep::Ref_t create_element(dd4hep::Detector& description, xml_h e, dd4h } DECLARE_DETELEMENT(DriftChamber_o1_v01, create_element) - From 5164fd216c4e85d0c775cbecad8d3803323879ed Mon Sep 17 00:00:00 2001 From: BrieucF Date: Wed, 6 Dec 2023 09:54:09 +0100 Subject: [PATCH 17/29] [DriftChamber] Sensitive detector type from xml --- detector/tracker/DriftChamber_o1_v01.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/detector/tracker/DriftChamber_o1_v01.cpp b/detector/tracker/DriftChamber_o1_v01.cpp index f16c46470..34b12d7e4 100644 --- a/detector/tracker/DriftChamber_o1_v01.cpp +++ b/detector/tracker/DriftChamber_o1_v01.cpp @@ -798,7 +798,8 @@ static dd4hep::Ref_t create_element(dd4hep::Detector& description, xml_h e, dd4h builder.build_layer(CDCH_det, envelope, sens_det); dd4hep::printout(dd4hep::DEBUG, "CreateCDCH", "MotherVolume is: %s", envelope.name()); - sens_det.setType("tracker"); + dd4hep::xml::Dimension sdType = x_det.child(_U(sensitive)); + sens_det.setType(sdType.typeStr()); builder.buildVolumes(e); builder.placeDaughters(CDCH_det, envelope, e); From 9223d03e722c20a6cb3a30bfa288f020182396db Mon Sep 17 00:00:00 2001 From: BrieucF Date: Wed, 6 Dec 2023 10:12:08 +0100 Subject: [PATCH 18/29] [DriftChamber] More cosmetics --- .../IDEA_o1_v02/DriftChamber_o1_v01.xml | 13 ++++--- detector/tracker/DriftChamber_o1_v01.cpp | 34 +++++++++---------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml index 035f416e4..addb730d3 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v02/DriftChamber_o1_v01.xml @@ -19,9 +19,9 @@ - + - + + + @@ -90,9 +93,9 @@ - - - + + + diff --git a/detector/tracker/DriftChamber_o1_v01.cpp b/detector/tracker/DriftChamber_o1_v01.cpp index 34b12d7e4..e534665c5 100644 --- a/detector/tracker/DriftChamber_o1_v01.cpp +++ b/detector/tracker/DriftChamber_o1_v01.cpp @@ -133,6 +133,10 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double InGWireShellThickOut = dd4hep::_toDouble("CDCH:InGWireShellThickOut"); double OutGWireShellThickIn = dd4hep::_toDouble("CDCH:OutGWireShellThickIn"); double OutGWireShellThickOut = dd4hep::_toDouble("CDCH:OutGWireShellThickOut"); + //------------------------------------------------------------------------ + // The wireThicknessDilution parameter is used to see the wires in the rendering. NB: not propagated to the envelope volumes --> you will have volume extrusions if != 1 + //------------------------------------------------------------------------ + double wireThicknessDilution = dd4hep::_toDouble("CDCH:wireThicknessDilution"); double secure = dd4hep::_toDouble("CDCH:secure"); double capGasLayer = dd4hep::_toDouble("CDCH:capGasLayer"); double extShiftFW = dd4hep::_toDouble("CDCH:extShiftFW"); @@ -192,12 +196,6 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double layer_inner_radius_at_z_end_whole_cell = 0.0; double epsilonIn_whole_cell = 0.0; - //------------------------------------------------------------------------ - // The enlarge parameter is used to see the wires in the rendering. NB: not propagated to the envelope volumes --> you will have volume extrusions if != 1 - //------------------------------------------------------------------------ - - double enlarge = 10.; - //------------------------------------------------------------------------ // Build the inner, outer and endcap walls first //------------------------------------------------------------------------ @@ -295,7 +293,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti dd4hep::Hyperboloid HypeLayer0(guard_layer_inner_radius_at_z_0, 0.0, layer_outer_radius_at_z_0 - secure, stereoOut0, halflength); lvLayerVol.push_back(dd4hep::Volume("hyperboloid_inner_guard_layer", HypeLayer0, description.material("GasHe_90Isob_10"))); - lvLayerVol.back().setVisAttributes(description, "vCDCH:Pb"); + lvLayerVol.back().setVisAttributes(description, gascol); epsilonInGwRing = atan(inGuardRad * (1.0 + dropFactor) * epsilonFactor); zlength = halflength; @@ -309,7 +307,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti guard_wires.delta_phi = 2. * TMath::Pi() / guard_wires.num; guard_wires.phioffset = phi_offset_cell_start; guard_wires.stereo = epsilonInGwRing; - guard_wires.thickness = 0.5 * InGWireShellThickIn * enlarge; // half the inner thickness as radius of tube + guard_wires.thickness = 0.5 * InGWireShellThickIn * wireThicknessDilution; // half the inner thickness as radius of tube guard_wires.halflength = zlength; guard_wires.name = string("Gwire_inner_stereoplus"); @@ -348,12 +346,12 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_top.delta_phi = 2. * TMath::Pi() /field_wires_top.num;; field_wires_top.phioffset = phi_offset_cell_start + cellStaggering - phi_offset; field_wires_top.stereo = sign_epsilon * epsilon; - field_wires_top.thickness = 0.5 * FWireShellThickIn * enlarge; + field_wires_top.thickness = 0.5 * FWireShellThickIn * wireThicknessDilution; field_wires_top.halflength = zlength; dd4hep::Hyperboloid HypeLayer1(layer_inner_radius_at_z_0, epsilonIn, layer_outer_radius_at_z_0 + field_wires_top.thickness + 0.5 * FWireShellThickOut, epsilonOut, halflength); lvLayerVol.push_back(dd4hep::Volume("hyperboloid_first_field_wire_ring", HypeLayer1, description.material("GasHe_90Isob_10"))); - lvLayerVol.back().setVisAttributes(description, "vCDCH:Plastic"); + lvLayerVol.back().setVisAttributes(description, gascol); field_wires_top.mother_volume = lvLayerVol.back(); lvFwireName = dd4hep::_toString(SL, "lvFwire_%d_init"); @@ -422,7 +420,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_bottom.delta_phi = delta_phi_top_bottom; field_wires_bottom.phioffset = phi_offset_cell_start + cellStaggering; field_wires_bottom.stereo = sign_epsilon * epsilon; - field_wires_bottom.thickness = 0.5 * FWireShellThickIn * enlarge; + field_wires_bottom.thickness = 0.5 * FWireShellThickIn * wireThicknessDilution; field_wires_bottom.halflength = zlength; field_wires_bottom.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(ilayer, "_layer%d") + string("_type") + field_wires_bottom.type + dd4hep::_toString(field_wires_bottom.stereo, "_stereo%f_bottom"); @@ -485,7 +483,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti sense_wires.delta_phi = sense_wire_delta_phi; sense_wires.phioffset = cellStaggering; sense_wires.stereo = sign_epsilon * epsilon; - sense_wires.thickness = 0.5 * SWireShellThickIn * enlarge; + sense_wires.thickness = 0.5 * SWireShellThickIn * wireThicknessDilution; sense_wires.halflength = zlength; sense_wires.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(ilayer, "_layer%d") + string("_type") + sense_wires.type + dd4hep::_toString(sense_wires.stereo, "_stereo%f"); @@ -511,7 +509,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_center.delta_phi = 2. * TMath::Pi() / field_wires_center.num; field_wires_center.phioffset = phi_offset_cell_start + cellStaggering; field_wires_center.stereo = sign_epsilon * epsilon; - field_wires_center.thickness = 0.5 * centerFWireShellThickIn * enlarge; + field_wires_center.thickness = 0.5 * centerFWireShellThickIn * wireThicknessDilution; field_wires_center.halflength = zlength; field_wires_center.volume = FwireVol; field_wires_center.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(ilayer, "_layer%d") + string("_type") + field_wires_center.type + dd4hep::_toString(field_wires_center.stereo, "_stereo%f_center"); @@ -564,7 +562,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_top.delta_phi = delta_phi_top_bottom; field_wires_top.phioffset = phi_offset_cell_start + cellStaggering; field_wires_top.stereo = sign_epsilon * epsilon; - field_wires_top.thickness = 0.5 * FWireShellThickIn * enlarge; + field_wires_top.thickness = 0.5 * FWireShellThickIn * wireThicknessDilution; field_wires_top.halflength = zlength; field_wires_top.volume = FwireVol; field_wires_top.name = dd4hep::_toString(SL, "Wire_SL%d") + dd4hep::_toString(ilayer, "_layer%d") + string("_type") + field_wires_top.type + dd4hep::_toString(field_wires_top.stereo, "_stereo%f_top"); @@ -667,7 +665,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti dd4hep::Hyperboloid HypeLayerOut(layer_inner_radius_at_z_0, epsilonIn, layer_outer_radius_at_z_0, epsilonOut, halflength); lvLayerVol.push_back(dd4hep::Volume("hyperboloid_last_field_wire_ring", HypeLayerOut, description.material("GasHe_90Isob_10"))); - lvLayerVol.back().setVisAttributes(description, "vCDCH:Plastic"); + lvLayerVol.back().setVisAttributes(description, gascol); zlength = halflength; zlength -= sin(epsilon) * FWradii; @@ -680,7 +678,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_bottom.delta_phi = 2. * TMath::Pi() / field_wires_bottom.num; field_wires_bottom.phioffset = phi_offset_cell_start + cellStaggering + phi_offset; field_wires_bottom.stereo = -1. * sign_epsilon * epsilon; - field_wires_bottom.thickness = 0.5 * FWireShellThickIn * enlarge; + field_wires_bottom.thickness = 0.5 * FWireShellThickIn * wireThicknessDilution; field_wires_bottom.halflength = zlength; lvFwireName = dd4hep::_toString(SL, "lvFwire_%d_out"); @@ -707,7 +705,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti dd4hep::Hyperboloid HypeLayerOutG(layer_inner_radius_at_z_0, epsilonOut, outer_radius - envelop_Outer_thickness - 0.0001, 0.0, halflength); lvLayerVol.push_back(dd4hep::Volume("hyperboloid_outer_guard_layer", HypeLayerOutG, description.material("GasHe_90Isob_10"))); - lvLayerVol.back().setVisAttributes(description, "vCDCH:Pb"); + lvLayerVol.back().setVisAttributes(description, gascol); epsilonOutGwRing = atan(outGuardRad * (1.0 + dropFactor) * epsilonFactor); zlength = halflength; @@ -721,7 +719,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti guard_wires.delta_phi = 2. * TMath::Pi() / guard_wires.num; guard_wires.phioffset = phi_offset_cell_start; guard_wires.stereo = epsilonOutGwRing; - guard_wires.thickness = 0.5 * OutGWireShellThickIn * enlarge; + guard_wires.thickness = 0.5 * OutGWireShellThickIn * wireThicknessDilution; guard_wires.halflength = zlength; guard_wires.name = string("Gwire_outer_stereominus"); From aea1539e41d5967a93c4cd9987787109dc40ccf5 Mon Sep 17 00:00:00 2001 From: BrieucF Date: Wed, 6 Dec 2023 10:21:50 +0100 Subject: [PATCH 19/29] [DriftChamber] Renaming --- detector/tracker/DriftChamber_o1_v01.cpp | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/detector/tracker/DriftChamber_o1_v01.cpp b/detector/tracker/DriftChamber_o1_v01.cpp index e534665c5..3e29e3d21 100644 --- a/detector/tracker/DriftChamber_o1_v01.cpp +++ b/detector/tracker/DriftChamber_o1_v01.cpp @@ -178,8 +178,8 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double fakeLayerInIWthick = -0.0001 + GasInnerWallThick; double guard_layer_inner_radius_at_z_0 = inner_radius + envelop_Inner_thickness - fakeLayerInIWthick; - double radius_layer_0 = inner_radius + envelop_Inner_thickness + FWradii + secure + capGasLayer; - double layer_outer_radius_at_z_0 = radius_layer_0 - FWradii - secure; + double layer_inner_radius_at_z_0 = inner_radius + envelop_Inner_thickness + FWradii + secure + capGasLayer; + double layer_outer_radius_at_z_0 = layer_inner_radius_at_z_0 - FWradii - secure; double drop = 0.0; double radius_layer = 0.0; @@ -325,12 +325,12 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti guard_wires.name = string("Gwire_inner_stereominus"); CDCHBuild::PlaceGuardWires(guard_wires, FWireShellThickOut, halflength, SL, -1); - drop = radius_layer_0 * dropFactor; - radius_layer = radius_layer_0 + drop; + drop = layer_inner_radius_at_z_0 * dropFactor; + radius_layer = layer_inner_radius_at_z_0 + drop; epsilon = atan(radius_layer * epsilonFactor); - layer_inner_radius_at_z_0 = radius_layer_0 - FWradii - 2.0 * secure; + layer_inner_radius_at_z_0 = layer_inner_radius_at_z_0 - FWradii - 2.0 * secure; layer_inner_radius_at_z_end = layer_inner_radius_at_z_0 + drop; - layer_outer_radius_at_z_0 = radius_layer_0 + FWradii; + layer_outer_radius_at_z_0 = layer_inner_radius_at_z_0 + FWradii; layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; epsilonIn = atan(sqrt(pow(layer_inner_radius_at_z_end, 2) - pow(layer_inner_radius_at_z_0, 2)) / halflength); epsilonOut = atan(sqrt(pow(layer_outer_radius_at_z_end, 2) - pow(layer_outer_radius_at_z_0, 2)) / halflength); @@ -364,7 +364,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_top.volume = lvFwireVol.back(); CDCHBuild::PlaceGuardWires(field_wires_top, FWireShellThickOut, halflength, SL, -1); - radius_layer_0 += FWradii; + layer_inner_radius_at_z_0 += FWradii; } else { delta_radius_layer = 2. * TMath::Pi() * layer_outer_radius_at_z_0 / (nSWire - TMath::Pi()); @@ -380,7 +380,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // on top of the following one, so new layerIn = old layerOut //------------------------------------------------------------------------ - sense_wire_radius_at_z_0 = radius_layer_0 + 0.5 * delta_radius_layer; + sense_wire_radius_at_z_0 = layer_inner_radius_at_z_0 + 0.5 * delta_radius_layer; sign_epsilon *= -1; layer_inner_radius_at_z_0 = layer_outer_radius_at_z_0; @@ -445,14 +445,14 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // Next, fill the geometry parameters of the central layer. //------------------------------------------------------------------------ - iradius = radius_layer_0; - radius_layer_0 += delta_radius_layer; - drop = radius_layer_0 * dropFactor; + iradius = layer_inner_radius_at_z_0; + layer_inner_radius_at_z_0 += delta_radius_layer; + drop = layer_inner_radius_at_z_0 * dropFactor; layer_inner_radius_at_z_0 = layer_outer_radius_at_z_0; layer_inner_radius_at_z_end = layer_outer_radius_at_z_end; epsilonIn = epsilonOut; - layer_outer_radius_at_z_0 = radius_layer_0 - FWireDiameter - 2.0 * secure; + layer_outer_radius_at_z_0 = layer_inner_radius_at_z_0 - FWireDiameter - 2.0 * secure; layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; epsilonOut = atan(sqrt(diff_of_squares(layer_outer_radius_at_z_end, layer_outer_radius_at_z_0)) / halflength); zlength = halflength; @@ -659,7 +659,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti layer_inner_radius_at_z_0 = layer_outer_radius_at_z_0; layer_inner_radius_at_z_end = layer_outer_radius_at_z_end; epsilonIn = epsilonOut; - layer_outer_radius_at_z_0 = radius_layer_0 + FWireDiameter + 2.0 * secure; + layer_outer_radius_at_z_0 = layer_inner_radius_at_z_0 + FWireDiameter + 2.0 * secure; layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; epsilonOut = atan(sqrt(diff_of_squares(layer_outer_radius_at_z_end, layer_outer_radius_at_z_0)) / halflength); @@ -698,7 +698,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti layer_inner_radius_at_z_0 = layer_outer_radius_at_z_0; layer_inner_radius_at_z_end = layer_outer_radius_at_z_end; epsilonIn = epsilonOut; - layer_outer_radius_at_z_0 = radius_layer_0 + FWireDiameter + 2.0 * secure; + layer_outer_radius_at_z_0 = layer_inner_radius_at_z_0 + FWireDiameter + 2.0 * secure; layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; epsilonOut = atan(sqrt(diff_of_squares(layer_outer_radius_at_z_end, layer_outer_radius_at_z_0)) / halflength); From d888715f41cef53f97b83aee2a096d6bb389aa33 Mon Sep 17 00:00:00 2001 From: BrieucF Date: Wed, 6 Dec 2023 11:23:04 +0100 Subject: [PATCH 20/29] [DriftChamber] Readme --- detector/tracker/README.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/detector/tracker/README.md b/detector/tracker/README.md index c7e2a1104..9fcd82d32 100644 --- a/detector/tracker/README.md +++ b/detector/tracker/README.md @@ -12,7 +12,7 @@ More details can be found in the talks at the [FCC week 2023](https://indico.cer This sub-detector implements a simplied drift chamber (there is no actual wire). It is used in ALLEGRO and IDEA detector concepts. ### o1_v01 -Original version taken from [FCCDetectors](https://github.com/HEP-FCC/FCCDetectors/blob/70a989a6fc333610e3b1b979c3596da9c41543d8/Detector/DetFCChhCalDiscs/src/CaloEndcapDiscs_geo.cpp). +Original version taken from [FCCDetectors](https://github.com/HEP-FCC/FCCDetectors/blob/main/Detector/DetSensitive/src/SimpleDriftChamber.cpp). ## DriftChamber Detailed (i.e. including wires) description of a unique-volume, high granularity, fully stereo, low mass, cylindrical drift chamber. @@ -20,8 +20,13 @@ Originally designed for the IDEA detector, it will be used also for the ALLEGRO A detailed description of the detector it tries to model can be found [here](https://indico.cern.ch/event/932973/contributions/4041314/attachments/2139657/3664808/primavera_FCCworkshop_2020.pdf) or [here](https://indico.cern.ch/event/1283129/contributions/5476695/attachments/2682660/4654170/DeFilippis_DCH_CC.pdf). ### o1_v01 -First version with all wires, walls, etc. -This version do not rely on any external segmentation, all volumes are defined in the detector builder. -The sensitive cell volume is a rotated (to get the stereo angle) tube segment that are put inside a hyperboloid for each layer. -The hyperboloid is theoretically not needed, but it help a lot to have a well balanced volume tree. -This first version can clearly be improved and still suffers from some overlap but it already enables further technical developments (digitization, tracking, particle flow, ...). +Very first version of the detailed drift chamber with wires, walls, etc. Taken from an early prototype available in FCCDetectors ([link](https://github.com/HEP-FCC/FCCDetectors/blob/main/Detector/DetFCCeeIDEA/src/DriftChamber.cpp)) and started to debug it, clean it and add the sensitive volume definition. +It is clearly not finished but made available to enable further technical developments on the digitization, tracking, particle flow, ... +This version do not rely on any external segmentation, all volumes are defined in the detector builder. +The sensitive cell volume is a rotated (to get the stereo angle and phi position) tube segment that are put inside a hyperboloid for each layer. +The hyperboloid is needed for performance, it helps having a well balanced volume tree. +What to improve: +- sensitive volume definition: fix volume extrusion/overlaps/wholes which can be partially solved by using "intersection solids" but this in turn makes the geometry building very slow and memory demanding (~10GB RAM). Other shapes like twisted tubes (caveat: no TGeo shape equivalent), tessalated solids or extruded volumes should be investigated for the next iteration. +- 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 From 28aa01989535fb2680cd974e6bbbc4fcd04c8e6a Mon Sep 17 00:00:00 2001 From: BrieucF Date: Wed, 6 Dec 2023 13:02:14 +0100 Subject: [PATCH 21/29] [IDEA] Uncomment vtx + beampipe imports --- FCCee/IDEA/compact/IDEA_o1_v02/IDEA_o1_v02.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 210d253f6..5ea3592ad 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v02/IDEA_o1_v02.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v02/IDEA_o1_v02.xml @@ -33,13 +33,13 @@ - - Import vertex - --> + + From ba98e305c9ec5fca1b7a15970ec5789ea5ffdfce Mon Sep 17 00:00:00 2001 From: BrieucF Date: Wed, 6 Dec 2023 13:19:02 +0100 Subject: [PATCH 22/29] [DriftChamber] Fix compilation --- detector/tracker/DriftChamber_o1_v01.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/detector/tracker/DriftChamber_o1_v01.cpp b/detector/tracker/DriftChamber_o1_v01.cpp index 3e29e3d21..e204db302 100644 --- a/detector/tracker/DriftChamber_o1_v01.cpp +++ b/detector/tracker/DriftChamber_o1_v01.cpp @@ -180,12 +180,11 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double layer_inner_radius_at_z_0 = inner_radius + envelop_Inner_thickness + FWradii + secure + capGasLayer; double layer_outer_radius_at_z_0 = layer_inner_radius_at_z_0 - FWradii - secure; + double layer_inner_radius_at_z_end = 0.0; + double layer_outer_radius_at_z_end = 0.0; double drop = 0.0; double radius_layer = 0.0; - double layer_inner_radius_at_z_0 = 0.0; - double layer_inner_radius_at_z_end = 0.0; - double layer_outer_radius_at_z_end = 0.0; double epsilonIn = 0.0; double epsilonOut = 0.0; double phi_offset_cell_start = 0.0; From 7b215e9e168d1e44acdb1f01f7cc58e5467dc3ca Mon Sep 17 00:00:00 2001 From: BrieucF Date: Wed, 6 Dec 2023 16:48:03 +0100 Subject: [PATCH 23/29] [DriftChamber] Revert spurious renaming --- detector/tracker/DriftChamber_o1_v01.cpp | 29 ++++++++++++------------ 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/detector/tracker/DriftChamber_o1_v01.cpp b/detector/tracker/DriftChamber_o1_v01.cpp index e204db302..6023596f6 100644 --- a/detector/tracker/DriftChamber_o1_v01.cpp +++ b/detector/tracker/DriftChamber_o1_v01.cpp @@ -178,8 +178,9 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti double fakeLayerInIWthick = -0.0001 + GasInnerWallThick; double guard_layer_inner_radius_at_z_0 = inner_radius + envelop_Inner_thickness - fakeLayerInIWthick; - double layer_inner_radius_at_z_0 = inner_radius + envelop_Inner_thickness + FWradii + secure + capGasLayer; - double layer_outer_radius_at_z_0 = layer_inner_radius_at_z_0 - FWradii - secure; + double radius_layer_0 = inner_radius + envelop_Inner_thickness + FWradii + secure + capGasLayer; + double layer_outer_radius_at_z_0 = radius_layer_0 - FWradii - secure; + double layer_inner_radius_at_z_0 = 0.0; double layer_inner_radius_at_z_end = 0.0; double layer_outer_radius_at_z_end = 0.0; @@ -324,12 +325,12 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti guard_wires.name = string("Gwire_inner_stereominus"); CDCHBuild::PlaceGuardWires(guard_wires, FWireShellThickOut, halflength, SL, -1); - drop = layer_inner_radius_at_z_0 * dropFactor; - radius_layer = layer_inner_radius_at_z_0 + drop; + drop = radius_layer_0 * dropFactor; + radius_layer = radius_layer_0 + drop; epsilon = atan(radius_layer * epsilonFactor); - layer_inner_radius_at_z_0 = layer_inner_radius_at_z_0 - FWradii - 2.0 * secure; + layer_inner_radius_at_z_0 = radius_layer_0 - FWradii - 2.0 * secure; layer_inner_radius_at_z_end = layer_inner_radius_at_z_0 + drop; - layer_outer_radius_at_z_0 = layer_inner_radius_at_z_0 + FWradii; + layer_outer_radius_at_z_0 = radius_layer_0 + FWradii; layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; epsilonIn = atan(sqrt(pow(layer_inner_radius_at_z_end, 2) - pow(layer_inner_radius_at_z_0, 2)) / halflength); epsilonOut = atan(sqrt(pow(layer_outer_radius_at_z_end, 2) - pow(layer_outer_radius_at_z_0, 2)) / halflength); @@ -363,7 +364,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti field_wires_top.volume = lvFwireVol.back(); CDCHBuild::PlaceGuardWires(field_wires_top, FWireShellThickOut, halflength, SL, -1); - layer_inner_radius_at_z_0 += FWradii; + radius_layer_0 += FWradii; } else { delta_radius_layer = 2. * TMath::Pi() * layer_outer_radius_at_z_0 / (nSWire - TMath::Pi()); @@ -379,7 +380,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // on top of the following one, so new layerIn = old layerOut //------------------------------------------------------------------------ - sense_wire_radius_at_z_0 = layer_inner_radius_at_z_0 + 0.5 * delta_radius_layer; + sense_wire_radius_at_z_0 = radius_layer_0 + 0.5 * delta_radius_layer; sign_epsilon *= -1; layer_inner_radius_at_z_0 = layer_outer_radius_at_z_0; @@ -444,14 +445,14 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti // Next, fill the geometry parameters of the central layer. //------------------------------------------------------------------------ - iradius = layer_inner_radius_at_z_0; - layer_inner_radius_at_z_0 += delta_radius_layer; - drop = layer_inner_radius_at_z_0 * dropFactor; + iradius = radius_layer_0; + radius_layer_0 += delta_radius_layer; + drop = radius_layer_0 * dropFactor; layer_inner_radius_at_z_0 = layer_outer_radius_at_z_0; layer_inner_radius_at_z_end = layer_outer_radius_at_z_end; epsilonIn = epsilonOut; - layer_outer_radius_at_z_0 = layer_inner_radius_at_z_0 - FWireDiameter - 2.0 * secure; + layer_outer_radius_at_z_0 = radius_layer_0 - FWireDiameter - 2.0 * secure; layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; epsilonOut = atan(sqrt(diff_of_squares(layer_outer_radius_at_z_end, layer_outer_radius_at_z_0)) / halflength); zlength = halflength; @@ -658,7 +659,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti layer_inner_radius_at_z_0 = layer_outer_radius_at_z_0; layer_inner_radius_at_z_end = layer_outer_radius_at_z_end; epsilonIn = epsilonOut; - layer_outer_radius_at_z_0 = layer_inner_radius_at_z_0 + FWireDiameter + 2.0 * secure; + layer_outer_radius_at_z_0 = radius_layer_0 + FWireDiameter + 2.0 * secure; layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; epsilonOut = atan(sqrt(diff_of_squares(layer_outer_radius_at_z_end, layer_outer_radius_at_z_0)) / halflength); @@ -697,7 +698,7 @@ void CDCHBuild::build_layer(DetElement parent, Volume parentVol, dd4hep::Sensiti layer_inner_radius_at_z_0 = layer_outer_radius_at_z_0; layer_inner_radius_at_z_end = layer_outer_radius_at_z_end; epsilonIn = epsilonOut; - layer_outer_radius_at_z_0 = layer_inner_radius_at_z_0 + FWireDiameter + 2.0 * secure; + layer_outer_radius_at_z_0 = radius_layer_0 + FWireDiameter + 2.0 * secure; layer_outer_radius_at_z_end = layer_outer_radius_at_z_0 + drop; epsilonOut = atan(sqrt(diff_of_squares(layer_outer_radius_at_z_end, layer_outer_radius_at_z_0)) / halflength); From 9e0f715afbaaca29c18ce7cd5a4d2a247244290a Mon Sep 17 00:00:00 2001 From: Brieuc Francois Date: Mon, 11 Dec 2023 09:41:16 +0100 Subject: [PATCH 24/29] Update detector/tracker/README.md Co-authored-by: Juan Miguel Carceller <22276694+jmcarcell@users.noreply.github.com> --- detector/tracker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detector/tracker/README.md b/detector/tracker/README.md index 9fcd82d32..eb082172d 100644 --- a/detector/tracker/README.md +++ b/detector/tracker/README.md @@ -22,7 +22,7 @@ A detailed description of the detector it tries to model can be found [here](htt ### o1_v01 Very first version of the detailed drift chamber with wires, walls, etc. Taken from an early prototype available in FCCDetectors ([link](https://github.com/HEP-FCC/FCCDetectors/blob/main/Detector/DetFCCeeIDEA/src/DriftChamber.cpp)) and started to debug it, clean it and add the sensitive volume definition. It is clearly not finished but made available to enable further technical developments on the digitization, tracking, particle flow, ... -This version do not rely on any external segmentation, all volumes are defined in the detector builder. +This version does not rely on any external segmentation, all volumes are defined in the detector builder. The sensitive cell volume is a rotated (to get the stereo angle and phi position) tube segment that are put inside a hyperboloid for each layer. The hyperboloid is needed for performance, it helps having a well balanced volume tree. What to improve: From 7a0bbc9c895c5aebe0f180e6f3b5b64c1c67e9c1 Mon Sep 17 00:00:00 2001 From: Brieuc Francois Date: Mon, 11 Dec 2023 09:41:28 +0100 Subject: [PATCH 25/29] Update detector/tracker/README.md Co-authored-by: Juan Miguel Carceller <22276694+jmcarcell@users.noreply.github.com> --- detector/tracker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detector/tracker/README.md b/detector/tracker/README.md index eb082172d..2fa0265d4 100644 --- a/detector/tracker/README.md +++ b/detector/tracker/README.md @@ -26,7 +26,7 @@ This version does not rely on any external segmentation, all volumes are defined The sensitive cell volume is a rotated (to get the stereo angle and phi position) tube segment that are put inside a hyperboloid for each layer. The hyperboloid is needed for performance, it helps having a well balanced volume tree. What to improve: -- sensitive volume definition: fix volume extrusion/overlaps/wholes which can be partially solved by using "intersection solids" but this in turn makes the geometry building very slow and memory demanding (~10GB RAM). Other shapes like twisted tubes (caveat: no TGeo shape equivalent), tessalated solids or extruded volumes should be investigated for the next iteration. +- sensitive volume definition: fix volume extrusion/overlaps/wholes which can be partially solved by using "intersection solids" but this in turn makes the geometry building very slow and memory demanding (~10GB RAM). Other shapes like twisted tubes (caveat: no TGeo shape equivalent), tessellated solids or extruded volumes should be investigated for the next iteration. - 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 From 79af43d0b6310a2dcc97a784a35bb817855e96d2 Mon Sep 17 00:00:00 2001 From: Brieuc Francois Date: Mon, 11 Dec 2023 09:41:44 +0100 Subject: [PATCH 26/29] Update detector/tracker/README.md Co-authored-by: Juan Miguel Carceller <22276694+jmcarcell@users.noreply.github.com> --- detector/tracker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detector/tracker/README.md b/detector/tracker/README.md index 2fa0265d4..3fbe421fc 100644 --- a/detector/tracker/README.md +++ b/detector/tracker/README.md @@ -23,7 +23,7 @@ A detailed description of the detector it tries to model can be found [here](htt Very first version of the detailed drift chamber with wires, walls, etc. Taken from an early prototype available in FCCDetectors ([link](https://github.com/HEP-FCC/FCCDetectors/blob/main/Detector/DetFCCeeIDEA/src/DriftChamber.cpp)) and started to debug it, clean it and add the sensitive volume definition. It is clearly not finished but made available to enable further technical developments on the digitization, tracking, particle flow, ... This version does not rely on any external segmentation, all volumes are defined in the detector builder. -The sensitive cell volume is a rotated (to get the stereo angle and phi position) tube segment that are put inside a hyperboloid for each layer. +The sensitive cell volume is a rotated (to get the stereo angle and phi position) tube segment that is put inside a hyperboloid for each layer. The hyperboloid is needed for performance, it helps having a well balanced volume tree. What to improve: - sensitive volume definition: fix volume extrusion/overlaps/wholes which can be partially solved by using "intersection solids" but this in turn makes the geometry building very slow and memory demanding (~10GB RAM). Other shapes like twisted tubes (caveat: no TGeo shape equivalent), tessellated solids or extruded volumes should be investigated for the next iteration. From 562a26b4732e6b51060eacb1327e5494a912fc28 Mon Sep 17 00:00:00 2001 From: BrieucF Date: Mon, 11 Dec 2023 10:32:37 +0100 Subject: [PATCH 27/29] [IDEA] Add a comment to remember to cross check materials --- FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml index f68afa8b4..7a16ef472 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml @@ -354,7 +354,7 @@ - + From ebd1978880811ba76bc6259d1eac627a42073829 Mon Sep 17 00:00:00 2001 From: BrieucF Date: Thu, 14 Dec 2023 12:10:32 +0100 Subject: [PATCH 28/29] [IDEA] Remove the reminder to check material, since done --- FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml b/FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml index 7a16ef472..f68afa8b4 100644 --- a/FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml +++ b/FCCee/IDEA/compact/IDEA_o1_v02/materials_o1_v01.xml @@ -354,7 +354,7 @@ - + From 95a2441c6d4591b1245227d80d3aab9d4ea702e2 Mon Sep 17 00:00:00 2001 From: SwathiSasikumar Date: Mon, 18 Dec 2023 09:55:23 +0100 Subject: [PATCH 29/29] Change in the type of inclined calorimeter and adding units to cell size (#312) --- FCCee/CLD/compact/CLD_o4_v05/LAr_ECalBarrel.xml | 2 +- .../ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v01_geo.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/FCCee/CLD/compact/CLD_o4_v05/LAr_ECalBarrel.xml b/FCCee/CLD/compact/CLD_o4_v05/LAr_ECalBarrel.xml index 5f940463f..55519bd5a 100644 --- a/FCCee/CLD/compact/CLD_o4_v05/LAr_ECalBarrel.xml +++ b/FCCee/CLD/compact/CLD_o4_v05/LAr_ECalBarrel.xml @@ -96,7 +96,7 @@ - + diff --git a/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v01_geo.cpp b/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v01_geo.cpp index ab11803e4..dece89dde 100644 --- a/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v01_geo.cpp +++ b/detector/calorimeter/ECalBarrel_NobleLiquid_InclinedTrapezoids_o1_v01_geo.cpp @@ -626,8 +626,8 @@ static dd4hep::detail::Ref_t createECalBarrelInclined(dd4hep::Detector& aLcdd, caloLayer.outer_thickness = difference_bet_r1r2 / 2; caloLayer.absorberThickness = absorberThickness; - caloLayer.cellSize0 = 2; - caloLayer.cellSize1 = 2; + caloLayer.cellSize0 = 2 * dd4hep::mm; + caloLayer.cellSize1 = 2 * dd4hep::mm; caloData->layers.push_back(caloLayer); }