Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:11:17

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