Back to home page

EIC code displayed by LXR

 
 

    


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