Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-24 08:20:52

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