Back to home page

sPhenix code displayed by LXR

 
 

    


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

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/detail/BlueprintDrawer.hpp"
0013 #include "Acts/Detector/detail/BlueprintHelper.hpp"
0014 
0015 #include <exception>
0016 #include <fstream>
0017 
0018 namespace Acts::Experimental {
0019 class IInternalStructureBuilder {};
0020 }  // namespace Acts::Experimental
0021 
0022 BOOST_AUTO_TEST_SUITE(Experimental)
0023 
0024 BOOST_AUTO_TEST_CASE(BlueprintHelperSorting) {
0025   // Create  root node
0026   std::vector<Acts::BinningValue> detectorBinning = {Acts::binR};
0027   std::vector<Acts::ActsScalar> detectorBoundaries = {0., 50., 100.};
0028   auto detector = std::make_unique<Acts::Experimental::Blueprint::Node>(
0029       "detector", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
0030       detectorBoundaries, detectorBinning);
0031 
0032   BOOST_CHECK_EQUAL(detector->parent, nullptr);
0033   BOOST_CHECK(detector->children.empty());
0034   BOOST_CHECK_EQUAL(detector->name, "detector");
0035 
0036   std::vector<Acts::BinningValue> pixelsBinning = {Acts::binZ};
0037   std::vector<Acts::ActsScalar> pixelsBoundaries = {20., 50., 100.};
0038 
0039   auto pixels = std::make_unique<Acts::Experimental::Blueprint::Node>(
0040       "pixels", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
0041       pixelsBoundaries, pixelsBinning);
0042 
0043   std::vector<Acts::ActsScalar> beamPipeBoundaries = {0., 20., 100.};
0044   auto beamPipe = std::make_unique<Acts::Experimental::Blueprint::Node>(
0045       "beam_pipe", Acts::Transform3::Identity(), Acts::VolumeBounds::eOther,
0046       beamPipeBoundaries);
0047 
0048   std::vector<Acts::ActsScalar> gapBoundaries = {20., 50., 10.};
0049   auto gap0 = std::make_unique<Acts::Experimental::Blueprint::Node>(
0050       "gap0", Acts::Transform3::Identity() * Acts::Translation3(0., 0., -90.),
0051       Acts::VolumeBounds::eCylinder, gapBoundaries);
0052 
0053   std::vector<Acts::ActsScalar> layerBoundaries = {20., 50., 80.};
0054   auto layer = std::make_unique<Acts::Experimental::Blueprint::Node>(
0055       "layer", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
0056       layerBoundaries,
0057       std::make_shared<Acts::Experimental::IInternalStructureBuilder>());
0058 
0059   auto gap1 = std::make_unique<Acts::Experimental::Blueprint::Node>(
0060       "gap1", Acts::Transform3::Identity() * Acts::Translation3(0., 0., 90.),
0061       Acts::VolumeBounds::eCylinder, gapBoundaries);
0062 
0063   // Add the nodes in a random fashion
0064   pixels->add(std::move(gap1));
0065   pixels->add(std::move(gap0));
0066   pixels->add(std::move(layer));
0067   // Add pixels and beam pipe in reverse order
0068   detector->add(std::move(pixels));
0069   detector->add(std::move(beamPipe));
0070 
0071   std::ofstream fs("detector_unordered.dot");
0072   Acts::Experimental::detail::BlueprintDrawer::dotStream(fs, *detector);
0073   fs.close();
0074 
0075   // Sort the detector
0076   Acts::Experimental::detail::BlueprintHelper::sort(*detector);
0077 
0078   // Test the recursive sort worked
0079   BOOST_CHECK_EQUAL(detector->children.front()->name, "beam_pipe");
0080   BOOST_CHECK_EQUAL(detector->children.back()->name, "pixels");
0081   BOOST_CHECK_EQUAL(detector->children.back()->children.front()->name, "gap0");
0082   BOOST_CHECK_EQUAL(detector->children.back()->children[1u]->name, "layer");
0083   BOOST_CHECK_EQUAL(detector->children.back()->children.back()->name, "gap1");
0084 
0085   std::ofstream fs2("detector_ordered.dot");
0086   Acts::Experimental::detail::BlueprintDrawer::dotStream(fs2, *detector);
0087   fs2.close();
0088 }
0089 
0090 BOOST_AUTO_TEST_CASE(BlueprintCylindricalGapFilling) {
0091   // Detector dimensions
0092   Acts::ActsScalar detectorIr = 0.;
0093   Acts::ActsScalar detectorOr = 120.;
0094   Acts::ActsScalar detectorHz = 400.;
0095 
0096   // Beam pipe
0097   Acts::ActsScalar beamPipeOr = 20.;
0098 
0099   // Pixel system
0100   Acts::ActsScalar pixelIr = 25;
0101   Acts::ActsScalar pixelOr = 115;
0102   Acts::ActsScalar pixelEcHz = 50;
0103 
0104   auto innerBuilder =
0105       std::make_shared<Acts::Experimental::IInternalStructureBuilder>();
0106 
0107   // Create  root node
0108   std::vector<Acts::BinningValue> detectorBinning = {Acts::binR};
0109   std::vector<Acts::ActsScalar> detectorBoundaries = {detectorIr, detectorOr,
0110                                                       detectorHz};
0111 
0112   // The root node - detector
0113   auto detector = std::make_unique<Acts::Experimental::Blueprint::Node>(
0114       "detector", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
0115       detectorBoundaries, detectorBinning);
0116 
0117   // The beam pipe
0118   std::vector<Acts::ActsScalar> beamPipeBoundaries = {detectorIr, beamPipeOr,
0119                                                       detectorHz};
0120   auto beamPipe = std::make_unique<Acts::Experimental::Blueprint::Node>(
0121       "beam_pipe", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
0122       beamPipeBoundaries, innerBuilder);
0123   detector->add(std::move(beamPipe));
0124 
0125   // A pixel system
0126   std::vector<Acts::ActsScalar> pixelBoundaries = {pixelIr, pixelOr,
0127                                                    detectorHz};
0128   std::vector<Acts::BinningValue> pixelBinning = {Acts::binZ};
0129   auto pixel = std::make_unique<Acts::Experimental::Blueprint::Node>(
0130       "pixel", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
0131       pixelBoundaries, pixelBinning);
0132 
0133   // Nec: Small differences to check if the adjustments are made
0134   std::vector<Acts::ActsScalar> pixelEcBoundaries = {pixelIr, pixelOr - 5.,
0135                                                      pixelEcHz};
0136   std::vector<Acts::BinningValue> pixelEcBinning = {Acts::binZ};
0137 
0138   auto pixelNec = std::make_unique<Acts::Experimental::Blueprint::Node>(
0139       "pixelNec",
0140       Acts::Transform3::Identity() *
0141           Acts::Translation3(0., 0., -detectorHz + pixelEcHz),
0142       Acts::VolumeBounds::eCylinder, pixelEcBoundaries, pixelEcBinning);
0143 
0144   // Add a single encap layer
0145   std::vector<Acts::ActsScalar> pixelNecBoundaries = {pixelIr + 2, pixelOr - 7.,
0146                                                       10.};
0147   auto pixelNecLayer = std::make_unique<Acts::Experimental::Blueprint::Node>(
0148       "pixelNecLayer",
0149       Acts::Transform3::Identity() *
0150           Acts::Translation3(0., 0., -detectorHz + pixelEcHz),
0151       Acts::VolumeBounds::eCylinder, pixelNecBoundaries, innerBuilder);
0152 
0153   pixelNec->add(std::move(pixelNecLayer));
0154 
0155   // Barrel
0156   std::vector<Acts::ActsScalar> pixelBarrelBoundaries = {
0157       pixelIr + 1, pixelOr - 1., detectorHz - 2 * pixelEcHz};
0158   std::vector<Acts::BinningValue> pixelBarrelBinning = {Acts::binR};
0159 
0160   auto pixelBarrel = std::make_unique<Acts::Experimental::Blueprint::Node>(
0161       "pixelBarrel", Acts::Transform3::Identity(),
0162       Acts::VolumeBounds::eCylinder, pixelBarrelBoundaries, pixelBarrelBinning);
0163 
0164   std::vector<Acts::ActsScalar> pixelBarrelL0Boundaries = {
0165       60, 65., detectorHz - 2 * pixelEcHz};
0166   auto pixelBarrelL0 = std::make_unique<Acts::Experimental::Blueprint::Node>(
0167       "pixelBarrelL0", Acts::Transform3::Identity(),
0168       Acts::VolumeBounds::eCylinder, pixelBarrelL0Boundaries, innerBuilder);
0169 
0170   std::vector<Acts::ActsScalar> pixelBarrelL1Boundaries = {
0171       100, 105., detectorHz - 2 * pixelEcHz};
0172   auto pixelBarrelL1 = std::make_unique<Acts::Experimental::Blueprint::Node>(
0173       "pixelBarrelL1", Acts::Transform3::Identity(),
0174       Acts::VolumeBounds::eCylinder, pixelBarrelL1Boundaries, innerBuilder);
0175   pixelBarrel->add(std::move(pixelBarrelL0));
0176   pixelBarrel->add(std::move(pixelBarrelL1));
0177 
0178   auto pixelPec = std::make_unique<Acts::Experimental::Blueprint::Node>(
0179       "pixelPec",
0180       Acts::Transform3::Identity() *
0181           Acts::Translation3(0., 0., +detectorHz - pixelEcHz),
0182       Acts::VolumeBounds::eCylinder, pixelEcBoundaries, pixelEcBinning);
0183 
0184   std::vector<Acts::ActsScalar> pixelPecBoundaries = {pixelIr + 2, pixelOr - 7.,
0185                                                       10.};
0186   auto pixelPecLayer = std::make_unique<Acts::Experimental::Blueprint::Node>(
0187       "pixelPecLayer",
0188       Acts::Transform3::Identity() *
0189           Acts::Translation3(0., 0., detectorHz - pixelEcHz),
0190       Acts::VolumeBounds::eCylinder, pixelPecBoundaries, innerBuilder);
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   detector->add(std::move(pixel));
0200 
0201   std::ofstream fs("detector_with_gaps.dot");
0202   Acts::Experimental::detail::BlueprintDrawer::dotStream(fs, *detector);
0203   fs.close();
0204 
0205   // Simple test
0206   BOOST_CHECK_EQUAL(detector->children.size(), 2u);
0207   BOOST_CHECK_EQUAL(detector->children[0u]->name, "beam_pipe");
0208   BOOST_CHECK_EQUAL(detector->children[1u]->name, "pixel");
0209 
0210   // Now fill the gaps
0211   Acts::Experimental::detail::BlueprintHelper::fillGaps(*detector);
0212 
0213   // Do the tests again
0214   BOOST_CHECK_EQUAL(detector->children.size(), 4u);
0215   BOOST_CHECK_EQUAL(detector->children[0u]->name, "beam_pipe");
0216   BOOST_CHECK_EQUAL(detector->children[1u]->name, "detector_gap_0");
0217   BOOST_CHECK_EQUAL(detector->children[2u]->name, "pixel");
0218   BOOST_CHECK_EQUAL(detector->children[3u]->name, "detector_gap_1");
0219 
0220   // Adjustment of gap parameters
0221   BOOST_CHECK_EQUAL(detector->children[1u]->boundaryValues[0], beamPipeOr);
0222   BOOST_CHECK_EQUAL(detector->children[1u]->boundaryValues[1], pixelIr);
0223   BOOST_CHECK_EQUAL(detector->children[1u]->boundaryValues[2], detectorHz);
0224 
0225   BOOST_CHECK_EQUAL(detector->children[3u]->boundaryValues[0], pixelOr);
0226   BOOST_CHECK_EQUAL(detector->children[3u]->boundaryValues[1], detectorOr);
0227   BOOST_CHECK_EQUAL(detector->children[3u]->boundaryValues[2], detectorHz);
0228 
0229   // Check the pixel system: Nec / Barrel / Pec
0230   BOOST_CHECK_EQUAL(detector->children[2u]->children.size(), 3u);
0231   BOOST_CHECK_EQUAL(detector->children[2u]->children[0u]->children.size(), 3u);
0232   BOOST_CHECK_EQUAL(detector->children[2u]->children[1u]->children.size(), 5u);
0233   BOOST_CHECK_EQUAL(detector->children[2u]->children[2u]->children.size(), 3u);
0234 
0235   // Nec test
0236   BOOST_CHECK_EQUAL(
0237       detector->children[2u]->children[0u]->children[0]->boundaryValues[0],
0238       pixelIr);
0239   BOOST_CHECK_EQUAL(
0240       detector->children[2u]->children[0u]->children[0]->boundaryValues[1],
0241       pixelOr);
0242 
0243   BOOST_CHECK_EQUAL(
0244       detector->children[2u]->children[0u]->children[1]->boundaryValues[0],
0245       pixelIr);
0246   BOOST_CHECK_EQUAL(
0247       detector->children[2u]->children[0u]->children[1]->boundaryValues[1],
0248       pixelOr);
0249 
0250   BOOST_CHECK_EQUAL(
0251       detector->children[2u]->children[0u]->children[2]->boundaryValues[0],
0252       pixelIr);
0253   BOOST_CHECK_EQUAL(
0254       detector->children[2u]->children[0u]->children[2]->boundaryValues[1],
0255       pixelOr);
0256 
0257   std::ofstream fs2("detector_without_gaps.dot");
0258   Acts::Experimental::detail::BlueprintDrawer::dotStream(fs2, *detector);
0259   fs2.close();
0260 }
0261 
0262 BOOST_AUTO_TEST_CASE(BlueprintCylindricalGapException) {
0263   auto innerBuilder =
0264       std::make_shared<Acts::Experimental::IInternalStructureBuilder>();
0265 
0266   // The root node - detector
0267   std::vector<Acts::ActsScalar> detectorBoundaries = {0., 50., 100.};
0268   std::vector<Acts::BinningValue> detectorBinning = {Acts::binX};
0269   auto detector = std::make_unique<Acts::Experimental::Blueprint::Node>(
0270       "detector", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
0271       detectorBoundaries, detectorBinning);
0272 
0273   // Add a volume
0274   std::vector<Acts::ActsScalar> volTwoBoundaries = {0., 20., 100.};
0275   auto vol = std::make_unique<Acts::Experimental::Blueprint::Node>(
0276       "vol", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
0277       volTwoBoundaries, innerBuilder);
0278   detector->add(std::move(vol));
0279 
0280   // Throw because cylinders can not be binned in x
0281   BOOST_CHECK_THROW(
0282       Acts::Experimental::detail::BlueprintHelper::fillGaps(*detector),
0283       std::runtime_error);
0284 }
0285 
0286 BOOST_AUTO_TEST_SUITE_END()