Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-12 07:53:01

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 <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Detector/Blueprint.hpp"
0012 #include "Acts/Detector/CylindricalContainerBuilder.hpp"
0013 #include "Acts/Detector/DetectorBuilder.hpp"
0014 #include "Acts/Detector/DetectorComponents.hpp"
0015 #include "Acts/Detector/DetectorVolume.hpp"
0016 #include "Acts/Detector/GeometryIdGenerator.hpp"
0017 #include "Acts/Detector/IndexedRootVolumeFinderBuilder.hpp"
0018 #include "Acts/Detector/detail/BlueprintDrawer.hpp"
0019 #include "Acts/Detector/detail/BlueprintHelper.hpp"
0020 #include "Acts/Detector/interface/IInternalStructureBuilder.hpp"
0021 #include "Acts/Geometry/GeometryContext.hpp"
0022 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0023 #include "Acts/Navigation/InternalNavigation.hpp"
0024 #include "Acts/Surfaces/CylinderSurface.hpp"
0025 #include "Acts/Surfaces/DiscSurface.hpp"
0026 #include "Acts/Utilities/BinningData.hpp"
0027 
0028 #include <fstream>
0029 
0030 template <typename surface_type>
0031 class SurfaceBuilder : public Acts::Experimental::IInternalStructureBuilder {
0032  public:
0033   SurfaceBuilder(const Acts::Transform3& trf, double p0, double p1)
0034       : m_surface(Acts::Surface::makeShared<surface_type>(trf, p0, p1)) {}
0035   /// Conrstruct and return the internal structure creation
0036   ///
0037   /// @param gctx the geometry context at the creation of the internal structure
0038   ///
0039   /// @return a consistent set of detector volume internals
0040   Acts::Experimental::InternalStructure construct(
0041       [[maybe_unused]] const Acts::GeometryContext& gctx) const final {
0042     // Trivialities first: internal volumes
0043     std::vector<std::shared_ptr<Acts::Experimental::DetectorVolume>>
0044         internalVolumes = {};
0045     Acts::Experimental::ExternalNavigationDelegate internalVolumeUpdater =
0046         Acts::Experimental::tryNoVolumes();
0047 
0048     // Retrieve the layer surfaces
0049     Acts::Experimental::InternalNavigationDelegate internalCandidatesUpdater =
0050         Acts::Experimental::tryAllPortalsAndSurfaces();
0051 
0052     // Return the internal structure
0053     return Acts::Experimental::InternalStructure{
0054         {m_surface},
0055         internalVolumes,
0056         std::move(internalCandidatesUpdater),
0057         std::move(internalVolumeUpdater)};
0058   }
0059 
0060  private:
0061   std::shared_ptr<Acts::Surface> m_surface;
0062 };
0063 
0064 BOOST_AUTO_TEST_SUITE(Detector)
0065 
0066 BOOST_AUTO_TEST_CASE(CylindricalDetectorFromBlueprintTest) {
0067   Acts::GeometryContext tContext;
0068 
0069   // This tests shows how to careate cylindrical detector from a detector
0070   // blueprint.
0071   //
0072   // In general, the blueprint (lines below) is generated through reading in
0073   // or by parsing the geometry model (DD4heo, TGeo, Geant4, etc.). For
0074   // testing purpose, let us create the blueprint manually.
0075   //
0076 
0077   // Blueprint starts here ----------------
0078 
0079   // Detector dimensions
0080   double detectorIr = 0.;
0081   double detectorOr = 120.;
0082   double detectorHz = 400.;
0083 
0084   // Beam pipe
0085   double beamPipeOr = 20.;
0086 
0087   // Pixel system
0088   double pixelIr = 25;
0089   double pixelOr = 115;
0090   double pixelEcHz = 50;
0091   double pixelEcLayerHz = 10;
0092 
0093   // Create  root node
0094   std::vector<Acts::AxisDirection> detectorBinning = {
0095       Acts::AxisDirection::AxisR};
0096   std::vector<double> detectorBoundaries = {detectorIr, detectorOr, detectorHz};
0097 
0098   // The root node - detector
0099   auto detectorBpr = std::make_unique<Acts::Experimental::Gen2Blueprint::Node>(
0100       "detector", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
0101       detectorBoundaries, detectorBinning);
0102 
0103   // The beam pipe
0104   std::vector<double> beamPipeBoundaries = {detectorIr, beamPipeOr, detectorHz};
0105 
0106   auto beamPipeStructure =
0107       std::make_shared<SurfaceBuilder<Acts::CylinderSurface>>(
0108           Acts::Transform3::Identity(), 18, 0.99 * detectorHz);
0109   auto beamPipe = std::make_unique<Acts::Experimental::Gen2Blueprint::Node>(
0110       "beam_pipe", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
0111       beamPipeBoundaries, beamPipeStructure);
0112   detectorBpr->add(std::move(beamPipe));
0113 
0114   // A pixel system
0115   std::vector<double> pixelBoundaries = {pixelIr, pixelOr, detectorHz};
0116   std::vector<Acts::AxisDirection> pixelBinning = {Acts::AxisDirection::AxisZ};
0117   auto pixel = std::make_unique<Acts::Experimental::Gen2Blueprint::Node>(
0118       "pixel", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
0119       pixelBoundaries, pixelBinning);
0120 
0121   // Nec: Small differences to check if the adjustments are made
0122   std::vector<double> pixelEcBoundaries = {pixelIr, pixelOr - 5., pixelEcHz};
0123   std::vector<Acts::AxisDirection> pixelEcBinning = {
0124       Acts::AxisDirection::AxisZ};
0125 
0126   Acts::Transform3 pixelNecTransform =
0127       Acts::Transform3::Identity() *
0128       Acts::Translation3(0., 0., -detectorHz + pixelEcHz);
0129 
0130   auto pixelNec = std::make_unique<Acts::Experimental::Gen2Blueprint::Node>(
0131       "pixel_nec", pixelNecTransform, Acts::VolumeBounds::eCylinder,
0132       pixelEcBoundaries, pixelEcBinning);
0133 
0134   // Add a single encap layer
0135   std::vector<double> pixelNecBoundaries = {pixelIr + 2, pixelOr - 7.,
0136                                             pixelEcLayerHz};
0137 
0138   auto pixelNecLayerStructure =
0139       std::make_shared<SurfaceBuilder<Acts::DiscSurface>>(
0140           pixelNecTransform, pixelIr + 10., pixelOr - 10.);
0141 
0142   auto pixelNecLayer =
0143       std::make_unique<Acts::Experimental::Gen2Blueprint::Node>(
0144           "pixel_nec_layer", pixelNecTransform, Acts::VolumeBounds::eCylinder,
0145           pixelNecBoundaries, pixelNecLayerStructure);
0146 
0147   pixelNec->add(std::move(pixelNecLayer));
0148 
0149   // Barrel
0150   std::vector<double> pixelBarrelBoundaries = {pixelIr + 1, pixelOr - 1.,
0151                                                detectorHz - 2 * pixelEcHz};
0152   std::vector<Acts::AxisDirection> pixelBarrelBinning = {
0153       Acts::AxisDirection::AxisR};
0154 
0155   auto pixelBarrel = std::make_unique<Acts::Experimental::Gen2Blueprint::Node>(
0156       "pixel_barrel", Acts::Transform3::Identity(),
0157       Acts::VolumeBounds::eCylinder, pixelBarrelBoundaries, pixelBarrelBinning);
0158 
0159   auto pixelBarrelL0Structure =
0160       std::make_shared<SurfaceBuilder<Acts::CylinderSurface>>(
0161           Acts::Transform3::Identity(), 62.5, detectorHz - 2 * pixelEcHz - 10.);
0162   std::vector<double> pixelBarrelL0Boundaries = {60, 65.,
0163                                                  detectorHz - 2 * pixelEcHz};
0164   auto pixelBarrelL0 =
0165       std::make_unique<Acts::Experimental::Gen2Blueprint::Node>(
0166           "pixel_barrel_l0", Acts::Transform3::Identity(),
0167           Acts::VolumeBounds::eCylinder, pixelBarrelL0Boundaries,
0168           pixelBarrelL0Structure);
0169 
0170   auto pixelBarrelL1Structure =
0171       std::make_shared<SurfaceBuilder<Acts::CylinderSurface>>(
0172           Acts::Transform3::Identity(), 102.5,
0173           detectorHz - 2 * pixelEcHz - 10.);
0174 
0175   std::vector<double> pixelBarrelL1Boundaries = {100, 105.,
0176                                                  detectorHz - 2 * pixelEcHz};
0177   auto pixelBarrelL1 =
0178       std::make_unique<Acts::Experimental::Gen2Blueprint::Node>(
0179           "pixel_barrel_l1", Acts::Transform3::Identity(),
0180           Acts::VolumeBounds::eCylinder, pixelBarrelL1Boundaries,
0181           pixelBarrelL1Structure);
0182   pixelBarrel->add(std::move(pixelBarrelL0));
0183   pixelBarrel->add(std::move(pixelBarrelL1));
0184 
0185   Acts::Transform3 pixelPecTransform =
0186       Acts::Transform3::Identity() *
0187       Acts::Translation3(0., 0., detectorHz - pixelEcHz);
0188 
0189   auto pixelPec = std::make_unique<Acts::Experimental::Gen2Blueprint::Node>(
0190       "pixel_pec", pixelPecTransform, Acts::VolumeBounds::eCylinder,
0191       pixelEcBoundaries, pixelEcBinning);
0192 
0193   std::vector<double> pixelPecBoundaries = {pixelIr + 2, pixelOr - 7., 10.};
0194 
0195   auto pixelPecLayerStructure =
0196       std::make_shared<SurfaceBuilder<Acts::DiscSurface>>(
0197           pixelPecTransform, pixelIr + 10., pixelOr - 10.);
0198 
0199   auto pixelPecLayer =
0200       std::make_unique<Acts::Experimental::Gen2Blueprint::Node>(
0201           "pixel_pec_layer", pixelPecTransform, Acts::VolumeBounds::eCylinder,
0202           pixelPecBoundaries, pixelPecLayerStructure);
0203 
0204   pixelPec->add(std::move(pixelPecLayer));
0205 
0206   // Adding pixel
0207   pixel->add(std::move(pixelNec));
0208   pixel->add(std::move(pixelPec));
0209   pixel->add(std::move(pixelBarrel));
0210 
0211   detectorBpr->add(std::move(pixel));
0212 
0213   // An Indexed volume finder will be attached
0214   std::vector<Acts::AxisDirection> rootVolumeBinning = {
0215       Acts::AxisDirection::AxisZ, Acts::AxisDirection::AxisR};
0216   detectorBpr->rootVolumeFinderBuilder =
0217       std::make_shared<Acts::Experimental::IndexedRootVolumeFinderBuilder>(
0218           rootVolumeBinning);
0219 
0220   // A geo ID generator
0221   detectorBpr->geoIdGenerator =
0222       std::make_shared<Acts::Experimental::GeometryIdGenerator>(
0223           Acts::Experimental::GeometryIdGenerator::Config{},
0224           Acts::getDefaultLogger("RecursiveIdGenerator",
0225                                  Acts::Logging::VERBOSE));
0226 
0227   // Complete and fill gaps
0228   Acts::Experimental::detail::BlueprintHelper::fillGaps(*detectorBpr);
0229 
0230   std::fstream fs("cylindrical_detector_blueprint.dot", std::ios::out);
0231   Acts::Experimental::detail::BlueprintDrawer::dotStream(fs, *detectorBpr);
0232   fs.close();
0233 
0234   // ----------------------------- end of blueprint
0235 
0236   // Create a Cylindrical detector builder from this blueprint
0237   auto detectorBuilder =
0238       std::make_shared<Acts::Experimental::CylindricalContainerBuilder>(
0239           *detectorBpr, Acts::Logging::VERBOSE);
0240 
0241   // Detector builder
0242   Acts::Experimental::DetectorBuilder::Config dCfg;
0243   dCfg.auxiliary =
0244       "*** Test : auto generated cylindrical detector builder  ***";
0245   dCfg.name = "Cylindrical detector from blueprint";
0246   dCfg.builder = detectorBuilder;
0247   dCfg.geoIdGenerator = detectorBpr->geoIdGenerator;
0248 
0249   auto detector = Acts::Experimental::DetectorBuilder(dCfg).construct(tContext);
0250 
0251   BOOST_REQUIRE_NE(detector, nullptr);
0252 
0253   // There should be 14 volumes, and they should be built in order
0254   // beam_pipe
0255   // detector_gap_0
0256   // pixel_nec_gap_0
0257   // pixel_nec_layer
0258   // pixel_nec_gap_1
0259   // pixel_barrel_gap_0
0260   // pixel_barrel_l0
0261   // pixel_barrel_gap_1
0262   // pixel_barrel_l1
0263   // pixel_barrel_gap_2
0264   // pixel_pec_gap_0
0265   // pixel_pec_layer
0266   // pixel_pec_gap_1
0267   // detector_gap_1
0268   BOOST_CHECK_EQUAL(detector->volumes().size(), 14u);
0269   BOOST_CHECK_EQUAL(detector->volumes()[0]->name(), "beam_pipe");
0270   BOOST_CHECK_EQUAL(detector->volumes()[1]->name(), "detector_gap_0");
0271   BOOST_CHECK_EQUAL(detector->volumes()[2]->name(), "pixel_nec_gap_0");
0272   BOOST_CHECK_EQUAL(detector->volumes()[3]->name(), "pixel_nec_layer");
0273   BOOST_CHECK_EQUAL(detector->volumes()[4]->name(), "pixel_nec_gap_1");
0274   BOOST_CHECK_EQUAL(detector->volumes()[5]->name(), "pixel_barrel_gap_0");
0275   BOOST_CHECK_EQUAL(detector->volumes()[6]->name(), "pixel_barrel_l0");
0276   BOOST_CHECK_EQUAL(detector->volumes()[7]->name(), "pixel_barrel_gap_1");
0277   BOOST_CHECK_EQUAL(detector->volumes()[8]->name(), "pixel_barrel_l1");
0278   BOOST_CHECK_EQUAL(detector->volumes()[9]->name(), "pixel_barrel_gap_2");
0279   BOOST_CHECK_EQUAL(detector->volumes()[10]->name(), "pixel_pec_gap_0");
0280   BOOST_CHECK_EQUAL(detector->volumes()[11]->name(), "pixel_pec_layer");
0281   BOOST_CHECK_EQUAL(detector->volumes()[12]->name(), "pixel_pec_gap_1");
0282   BOOST_CHECK_EQUAL(detector->volumes()[13]->name(), "detector_gap_1");
0283 }
0284 
0285 BOOST_AUTO_TEST_SUITE_END()