Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-16 08:03:59

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