Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:13:08

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Geometry/VolumeBounds.hpp"
0010 #include "Acts/Plugins/DD4hep/DD4hepBinningHelpers.hpp"
0011 #include "Acts/Plugins/DD4hep/DD4hepConversionHelpers.hpp"
0012 #include "Acts/Utilities/Logger.hpp"
0013 
0014 #include <DD4hep/DetFactoryHelper.h>
0015 #include <DD4hep/Objects.h>
0016 #include <DDRec/DetectorData.h>
0017 #include <XML/Utilities.h>
0018 
0019 #include "DD4hepTestsHelper.hpp"
0020 
0021 using namespace dd4hep;
0022 
0023 /// @brief  Helper method to add a layer to the detector
0024 ///
0025 /// @param dd the detector to which this is added
0026 /// @param dAssembly the detector assembly
0027 /// @param x_layer the xml element describing the layer
0028 /// @param sens the sensitive detector to be used
0029 /// @param layerID the layer ID
0030 ///
0031 /// @return a DetElement
0032 DetElement addCylinderLayer(Detector &dd, Assembly &dAssembly,
0033                             const xml_comp_t &x_layer, SensitiveDetector sens,
0034                             int layerID) {
0035   // Make the cylinder detector element
0036   auto layerName = x_layer.nameStr();
0037   DetElement layerElement(layerName, layerID);
0038   // Layer parameters
0039   auto &layerParams =
0040       DD4hepTestsHelper::ensureExtension<dd4hep::rec::VariantParameters>(
0041           layerElement);
0042 
0043   // This should have a volume definition attached
0044   if (x_layer.hasChild(_Unicode(acts_volume))) {
0045     xml_comp_t actsVolume = x_layer.child(_Unicode(acts_volume));
0046     layerParams.set<bool>("acts_volume", true);
0047     layerParams.set<double>("acts_volume_z",
0048                             Acts::getAttrValueOr<double>(actsVolume, "cz", 0.));
0049     layerParams.set<int>("acts_volume_type", 3);
0050     layerParams.set<int>("acts_volume_bvalues_n", 3);
0051     layerParams.set<double>(
0052         "acts_volume_bvalues_0",
0053         Acts::getAttrValueOr<double>(actsVolume, "rmin", 0.));
0054     layerParams.set<double>(
0055         "acts_volume_bvalues_1",
0056         Acts::getAttrValueOr<double>(actsVolume, "rmax", 0.));
0057     layerParams.set<double>("acts_volume_bvalues_2",
0058                             Acts::getAttrValueOr<double>(actsVolume, "dz", 0.));
0059 
0060     layerParams.set<bool>("acts_volume_internals", true);
0061     layerParams.set<std::string>("acts_volume_internals_type", "layer");
0062   }
0063 
0064   // The layer Assembly
0065   Assembly layerAssembly(layerName + "_assembly");
0066   layerAssembly.setVisAttributes(dd, x_layer.visStr());
0067 
0068   // Active layer surfaces - Count and fill the sensors
0069   if (x_layer.hasChild(_Unicode(modules))) {
0070     // Check if the cylinder has a surface binning instruction
0071     if (x_layer.hasChild(_Unicode(acts_surface_binning))) {
0072       xml_comp_t sfBinning = x_layer.child(_Unicode(acts_surface_binning));
0073       DD4hepTestsHelper::decodeBinning(layerParams, sfBinning,
0074                                        "acts_surface_binning", {"z", "phi"});
0075     }
0076     // Go through the sensors
0077     unsigned int sensorID = 1u;
0078     xml_comp_t x_layer_modules = x_layer.child(_Unicode(modules));
0079     for (xml_coll_t bmodule(x_layer_modules, _U(box)); bmodule != nullptr;
0080          ++bmodule) {
0081       xml_comp_t x_layer_box = bmodule;
0082 
0083       // Due to convention this causes an axis flip on x
0084       Box boxShape(0.5 * x_layer_box.dx(), 0.5 * x_layer_box.dy(),
0085                    0.5 * x_layer_box.dz());
0086 
0087       // Set an orientation
0088       DetElement boxElement(layerName + "_module" + std::to_string(sensorID),
0089                             sensorID);
0090 
0091       Volume boxVolume(layerName, boxShape,
0092                        dd.material(x_layer_box.materialStr()));
0093       boxVolume.setVisAttributes(dd, x_layer_box.visStr());
0094       boxVolume.setSensitiveDetector(sens);
0095 
0096       PlacedVolume placedBox = layerAssembly.placeVolume(
0097           boxVolume, DD4hepTestsHelper::createTransform(x_layer_box));
0098 
0099       placedBox.addPhysVolID("sensor", sensorID++);
0100       boxElement.setPlacement(placedBox);
0101       // Add the module elements
0102       layerElement.add(boxElement);
0103     }
0104   }
0105   // Passive layer surface - place it inside the envelope
0106   for (xml_coll_t psurface(x_layer, _Unicode(acts_passive_surface));
0107        psurface != nullptr; ++psurface) {
0108     xml_comp_t x_passive_xml = psurface;
0109     // Direct definition of a child surface
0110     if (x_passive_xml.hasChild(_Unicode(tubs))) {
0111       xml_comp_t x_tubs_t = x_passive_xml.child(_Unicode(tubs));
0112       // Crete the corresponding detector element
0113       DetElement passiveElement(layerName + "_passiveEl", x_layer.id());
0114       Tube passiveShape(layerName + "_shape", x_tubs_t.rmin(), x_tubs_t.rmax(),
0115                         x_tubs_t.dz());
0116       Volume passiveVolume(layerName + "_volume", passiveShape,
0117                            dd.material(x_tubs_t.materialStr()));
0118       passiveVolume.setVisAttributes(dd, x_layer.visStr());
0119       // The places layer after all
0120       PlacedVolume placedPassive = layerAssembly.placeVolume(
0121           passiveVolume, DD4hepTestsHelper::createTransform(x_passive_xml));
0122       // Transport the passive surface knowledge
0123       auto &params =
0124           DD4hepTestsHelper::ensureExtension<dd4hep::rec::VariantParameters>(
0125               passiveElement);
0126       params.set<bool>("acts_passive_surface", true);
0127       // Set the placement and add
0128       passiveElement.setPlacement(placedPassive);
0129       // Add the module elements
0130       layerElement.add(passiveElement);
0131     }
0132   }
0133 
0134   auto placedLayer = dAssembly.placeVolume(layerAssembly);
0135   placedLayer.addPhysVolID("layer", layerID);
0136   layerElement.setPlacement(placedLayer);
0137   // Return the layer element
0138   return layerElement;
0139 }
0140 
0141 /// @brief  Helper method to add a layer to the detector
0142 ///
0143 /// @param dd the detector to which this is added
0144 /// @param dAssembly the detector assembly
0145 /// @param x_layer the xml element describing the layer
0146 /// @param sens the sensitive detector to be used
0147 /// @param layerID the layer ID
0148 ///
0149 /// @return a DetElement
0150 DetElement addDiscLayer(Detector &dd, Assembly &dAssembly,
0151                         const xml_comp_t &x_layer, SensitiveDetector sens,
0152                         int layerID) {
0153   // Make the cylinder detector element
0154   auto layerName = x_layer.nameStr();
0155   DetElement layerElement(layerName, layerID);
0156   // Layer parameters
0157   auto &layerParams =
0158       DD4hepTestsHelper::ensureExtension<dd4hep::rec::VariantParameters>(
0159           layerElement);
0160 
0161   // This should have a volume definition attached
0162   if (x_layer.hasChild(_Unicode(acts_volume))) {
0163     xml_comp_t actsVolume = x_layer.child(_Unicode(acts_volume));
0164     layerParams.set<bool>("acts_volume", true);
0165     layerParams.set<double>("acts_volume_z",
0166                             Acts::getAttrValueOr<double>(actsVolume, "cz", 0.));
0167     layerParams.set<int>("acts_volume_type", 3);
0168     layerParams.set<int>("acts_volume_bvalues_n", 3);
0169     layerParams.set<double>(
0170         "acts_volume_bvalues_0",
0171         Acts::getAttrValueOr<double>(actsVolume, "rmin", 0.));
0172     layerParams.set<double>(
0173         "acts_volume_bvalues_1",
0174         Acts::getAttrValueOr<double>(actsVolume, "rmax", 0.));
0175     layerParams.set<double>("acts_volume_bvalues_2",
0176                             Acts::getAttrValueOr<double>(actsVolume, "dz", 0.));
0177 
0178     layerParams.set<bool>("acts_volume_internals", true);
0179     layerParams.set<std::string>("acts_volume_internals_type", "layer");
0180   }
0181 
0182   // The layer Assembly
0183   Assembly layerAssembly(layerName);
0184   layerAssembly.setVisAttributes(dd, x_layer.visStr());
0185 
0186   // Active layer surfaces - Count and fill the sensors
0187   if (x_layer.hasChild(_Unicode(modules))) {
0188     // Check if the cylinder has a surface binning instruction
0189     if (x_layer.hasChild(_Unicode(acts_surface_binning))) {
0190       xml_comp_t sfBinning = x_layer.child(_Unicode(acts_surface_binning));
0191       DD4hepTestsHelper::decodeBinning(layerParams, sfBinning,
0192                                        "acts_surface_binning", {"r", "phi"});
0193     }
0194 
0195     // Loop over modules
0196     unsigned int sensorID = 1u;
0197     xml_comp_t x_layer_modules = x_layer.child(_Unicode(modules));
0198     for (xml_coll_t bmodule(x_layer_modules, _U(trap)); bmodule != nullptr;
0199          ++bmodule) {
0200       xml_comp_t x_layer_trap = bmodule;
0201 
0202       // Due to convention this causes an axis flip on x
0203       Trapezoid trapShape(0.5 * x_layer_trap.dz(), 0.5 * x_layer_trap.dz(),
0204                           x_layer_trap.x1(), x_layer_trap.x2(),
0205                           0.5 * x_layer_trap.dy());
0206 
0207       // Set an orientation
0208       DetElement trapElement(layerName + "_module" + std::to_string(sensorID),
0209                              sensorID);
0210       auto &params =
0211           DD4hepTestsHelper::ensureExtension<dd4hep::rec::VariantParameters>(
0212               trapElement);
0213       params.set<std::string>("axis_definitions", "YZ");
0214 
0215       Volume trapVolume(layerName + "_vol", trapShape,
0216                         dd.material(x_layer_trap.materialStr()));
0217       trapVolume.setVisAttributes(dd, x_layer.visStr());
0218       trapVolume.setSensitiveDetector(sens);
0219 
0220       PlacedVolume placedTrap = layerAssembly.placeVolume(
0221           trapVolume, DD4hepTestsHelper::createTransform(x_layer_trap));
0222 
0223       placedTrap.addPhysVolID("sensor", sensorID++);
0224       trapElement.setPlacement(placedTrap);
0225       // Add the module elements
0226       layerElement.add(trapElement);
0227     }
0228 
0229     // Passive layer surface - place it inside the envelope
0230     for (xml_coll_t psurface(x_layer, _Unicode(acts_passive_surface));
0231          psurface != nullptr; ++psurface) {
0232       xml_comp_t x_passive_xml = psurface;
0233       // Direct definition of a child surface
0234       if (x_passive_xml.hasChild(_Unicode(tubs))) {
0235         xml_comp_t x_tubs_t = x_passive_xml.child(_Unicode(tubs));
0236         // Create the corresponding detector element
0237         DetElement passiveElement(layerName + "_passiveEl", x_layer.id());
0238         Tube passiveShape(layerName + "_passiveShape", x_tubs_t.rmin(),
0239                           x_tubs_t.rmax(), x_tubs_t.dz());
0240         Volume passiveVolume(layerName + "_passiveVolume", passiveShape,
0241                              dd.material(x_tubs_t.materialStr()));
0242         passiveVolume.setVisAttributes(dd, x_layer.visStr());
0243         // The places layer after all
0244         PlacedVolume placedPassive = layerAssembly.placeVolume(
0245             passiveVolume, DD4hepTestsHelper::createTransform(x_passive_xml));
0246         // Transport the passive surface knowledge
0247         auto &params =
0248             DD4hepTestsHelper::ensureExtension<dd4hep::rec::VariantParameters>(
0249                 passiveElement);
0250         params.set<bool>("acts_passive_surface", true);
0251         // Set the placement and add
0252         passiveElement.setPlacement(placedPassive);
0253         // Add the module elements
0254         layerElement.add(passiveElement);
0255       }
0256     }
0257   }
0258   auto placedLayer = dAssembly.placeVolume(layerAssembly);
0259   placedLayer.addPhysVolID("layer", layerID);
0260   layerElement.setPlacement(placedLayer);
0261   // Return the layer element
0262   return layerElement;
0263 }
0264 
0265 /// Standard create_barrel_detector(...) create a barrel
0266 /// like detector
0267 ///
0268 /// @param dd the detector to which this is addedded
0269 /// @param xml the input xml element
0270 /// @param sens is ignored
0271 ///
0272 /// @return a reference counted DetElement
0273 static Ref_t create_barrel_detector(Detector &dd, xml_h xml,
0274                                     SensitiveDetector sens) {
0275   xml_det_t x_det = xml;
0276   std::string detName = x_det.nameStr();
0277 
0278   // create the master detector element
0279   DetElement detectorElement(detName, x_det.id());
0280   dd4hep::xml::setDetectorTypeFlag(xml, detectorElement);
0281 
0282   // The Shape and Volume
0283   Assembly detectorAssembly(detName);
0284   detectorAssembly.setVisAttributes(dd, x_det.visStr());
0285 
0286   // Add layers if they exist as such
0287   if (x_det.hasChild(_Unicode(layers))) {
0288     xml_comp_t x_det_layers = x_det.child(_Unicode(layers));
0289     int layerID = 0;
0290     for (xml_coll_t layer(x_det_layers, _Unicode(layer)); layer != nullptr;
0291          ++layer) {
0292       xml_comp_t x_det_layer = layer;
0293       auto layerElement =
0294           addCylinderLayer(dd, detectorAssembly, x_det_layer, sens, layerID++);
0295       // Add is to the detector element
0296       detectorElement.add(layerElement);
0297     }
0298   }
0299   // Place it into the mother volume
0300   Volume motherVolume = dd.pickMotherVolume(detectorElement);
0301   Position translation(0., 0., 0.);
0302   PlacedVolume placedDetector =
0303       motherVolume.placeVolume(detectorAssembly, translation);
0304   // "system" is hard coded in the DD4Hep::VolumeManager
0305   placedDetector.addPhysVolID("system", x_det.id());
0306   detectorElement.setPlacement(placedDetector);
0307 
0308   // return this element
0309   return detectorElement;
0310 }
0311 
0312 DECLARE_DETELEMENT(BarrelDetector, create_barrel_detector)
0313 
0314 /// Standard create_endcap_detector(...) create a simple disc layer
0315 ///
0316 /// @param dd the detector to which this is addedded
0317 /// @param xml the input xml element
0318 /// @param sens is ignored
0319 ///
0320 /// @return a reference counted DetElement
0321 static Ref_t create_endcap_detector(Detector &dd, xml_h xml,
0322                                     SensitiveDetector sens) {
0323   xml_det_t x_det = xml;
0324   std::string detName = x_det.nameStr();
0325 
0326   // create the master detector element
0327   DetElement detectorElement(detName, x_det.id());
0328   dd4hep::xml::setDetectorTypeFlag(xml, detectorElement);
0329 
0330   // The Shape and Volume
0331   Assembly detectorAssembly(detName);
0332   detectorAssembly.setVisAttributes(dd, x_det.visStr());
0333 
0334   // Add layers if they exist as such
0335   if (x_det.hasChild(_Unicode(layers))) {
0336     xml_comp_t x_det_layers = x_det.child(_Unicode(layers));
0337     int layerID = 0;
0338     for (xml_coll_t layer(x_det_layers, _Unicode(layer)); layer != nullptr;
0339          ++layer) {
0340       xml_comp_t x_det_layer = layer;
0341       auto layerElement =
0342           addDiscLayer(dd, detectorAssembly, x_det_layer, sens, layerID++);
0343       // Add the layer element to the detector element
0344       detectorElement.add(layerElement);
0345     }
0346   }
0347 
0348   // Place it into the mother volume
0349   Volume motherVolume = dd.pickMotherVolume(detectorElement);
0350   Position translation(0., 0., 0.);
0351   PlacedVolume placedDetector =
0352       motherVolume.placeVolume(detectorAssembly, translation);
0353   // "system" is hard coded in the DD4Hep::VolumeManager
0354   placedDetector.addPhysVolID("system", x_det.id());
0355   detectorElement.setPlacement(placedDetector);
0356 
0357   // return this element
0358   return detectorElement;
0359 }
0360 
0361 DECLARE_DETELEMENT(EndcapDetector, create_endcap_detector)