File indexing completed on 2025-10-18 08:22:23
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Detector/Blueprint.hpp"
0012 #include "Acts/Detector/CuboidalContainerBuilder.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/PlaneSurface.hpp"
0025 #include "Acts/Surfaces/RectangleBounds.hpp"
0026 #include "Acts/Surfaces/Surface.hpp"
0027 #include "Acts/Utilities/BinningData.hpp"
0028
0029 #include <algorithm>
0030 #include <fstream>
0031
0032 using namespace Acts;
0033
0034 namespace ActsTests {
0035
0036 class SurfaceBuilder : public Experimental::IInternalStructureBuilder {
0037 public:
0038 SurfaceBuilder(const Transform3& transform, const RectangleBounds& sBounds)
0039 : m_transform(transform), m_surfaceBounds(sBounds) {};
0040
0041
0042
0043
0044
0045
0046 Experimental::InternalStructure construct(
0047 [[maybe_unused]] const GeometryContext& gctx) const final {
0048 auto surface = Surface::makeShared<PlaneSurface>(
0049 (m_transform), std::make_shared<RectangleBounds>(m_surfaceBounds));
0050
0051
0052 std::vector<std::shared_ptr<Experimental::DetectorVolume>> internalVolumes =
0053 {};
0054 Experimental::ExternalNavigationDelegate internalVolumeUpdater =
0055 Experimental::tryNoVolumes();
0056
0057
0058 Experimental::InternalNavigationDelegate internalCandidatesUpdater =
0059 Experimental::tryAllPortalsAndSurfaces();
0060
0061
0062 return Experimental::InternalStructure{{surface},
0063 internalVolumes,
0064 std::move(internalCandidatesUpdater),
0065 std::move(internalVolumeUpdater)};
0066 }
0067
0068 private:
0069 Transform3 m_transform;
0070 RectangleBounds m_surfaceBounds;
0071 };
0072
0073 BOOST_AUTO_TEST_SUITE(DetectorSuite)
0074
0075 BOOST_AUTO_TEST_CASE(CuboidalDetectorFromBlueprintTest) {
0076 GeometryContext tContext;
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 double detectorX = 100.;
0090 double detectorY = 100.;
0091 double detectorZ = 100.;
0092
0093
0094 double pixelX = 20;
0095 double pixelY = 100;
0096 double pixelZ = 10;
0097
0098
0099 std::vector<AxisDirection> detectorBins = {AxisDirection::AxisX};
0100 std::vector<double> detectorBounds = {detectorX, detectorY, detectorZ};
0101
0102
0103 auto detectorBpr = std::make_unique<Experimental::Gen2Blueprint::Node>(
0104 "detector", Transform3::Identity(), VolumeBounds::eCuboid, detectorBounds,
0105 detectorBins);
0106
0107
0108 std::vector<double> leftArmBounds = {detectorX * 0.5, detectorY, detectorZ};
0109
0110 std::vector<AxisDirection> leftArmBins = {AxisDirection::AxisZ};
0111
0112 Transform3 leftArmTransform =
0113 Transform3::Identity() * Translation3(-detectorX * 0.5, 0., 0);
0114
0115 auto leftArm = std::make_unique<Experimental::Gen2Blueprint::Node>(
0116 "leftArm", leftArmTransform, VolumeBounds::eCuboid, leftArmBounds,
0117 leftArmBins);
0118
0119
0120 std::vector<double> pixelL1Boundaries = {pixelX, pixelY, pixelZ};
0121
0122 Transform3 pixelL1Transform =
0123 Transform3::Identity() *
0124 Translation3(-pixelX - 5, 0., -detectorZ + pixelZ + 5);
0125
0126 auto pixelL1Structure = std::make_shared<SurfaceBuilder>(
0127 pixelL1Transform, RectangleBounds(pixelX * 0.8, pixelY * 0.8));
0128
0129 auto pixelL1 = std::make_unique<Experimental::Gen2Blueprint::Node>(
0130 "pixelL1", pixelL1Transform, VolumeBounds::eCuboid, pixelL1Boundaries,
0131 pixelL1Structure);
0132
0133
0134 std::vector<double> pixelL2Boundaries = {pixelX, pixelY, pixelZ};
0135
0136 Transform3 pixelL2Transform =
0137 Transform3::Identity() *
0138 Translation3(-pixelX - 5, 0., -detectorZ + 2 * pixelZ + 5 * 5);
0139
0140 auto pixelL2Structure = std::make_shared<SurfaceBuilder>(
0141 pixelL2Transform, RectangleBounds(pixelX * 0.8, pixelY * 0.8));
0142
0143 auto pixelL2 = std::make_unique<Experimental::Gen2Blueprint::Node>(
0144 "pixelL2", pixelL2Transform, VolumeBounds::eCuboid, pixelL2Boundaries,
0145 pixelL2Structure);
0146
0147
0148
0149 leftArm->add(std::move(pixelL1));
0150 leftArm->add(std::move(pixelL2));
0151 detectorBpr->add(std::move(leftArm));
0152
0153
0154 std::vector<double> rightArmBounds = {detectorX * 0.5, detectorY, detectorZ};
0155
0156 std::vector<AxisDirection> rightArmBins = {AxisDirection::AxisZ};
0157
0158 Transform3 rightArmTransform =
0159 Transform3::Identity() * Translation3(detectorX * 0.5, 0., 0);
0160
0161 auto rightArm = std::make_unique<Experimental::Gen2Blueprint::Node>(
0162 "rightArm", rightArmTransform, VolumeBounds::eCuboid, rightArmBounds,
0163 rightArmBins);
0164
0165
0166 std::vector<double> pixelR1Boundaries = {pixelX, pixelY, pixelZ};
0167
0168 Transform3 pixelR1Transform =
0169 Transform3::Identity() *
0170 Translation3(pixelX + 5, 0., -detectorZ + pixelZ + 5);
0171
0172 auto pixelR1Structure = std::make_shared<SurfaceBuilder>(
0173 pixelR1Transform, RectangleBounds(pixelX * 0.8, pixelY * 0.8));
0174
0175 auto pixelR1 = std::make_unique<Experimental::Gen2Blueprint::Node>(
0176 "pixelR1", pixelR1Transform, VolumeBounds::eCuboid, pixelR1Boundaries,
0177 pixelR1Structure);
0178
0179
0180 std::vector<double> pixelR2Boundaries = {pixelX, pixelY, pixelZ};
0181
0182 Transform3 pixelR2Transform =
0183 Transform3::Identity() *
0184 Translation3(pixelX + 5, 0., -detectorZ + 2 * pixelZ + 5 * 5);
0185
0186 auto pixelR2Structure = std::make_shared<SurfaceBuilder>(
0187 pixelR2Transform, RectangleBounds(pixelX * 0.8, pixelY * 0.8));
0188
0189 auto pixelR2 = std::make_unique<Experimental::Gen2Blueprint::Node>(
0190 "pixelR2", pixelR2Transform, VolumeBounds::eCuboid, pixelR2Boundaries,
0191 pixelR2Structure);
0192
0193
0194
0195 rightArm->add(std::move(pixelR1));
0196 rightArm->add(std::move(pixelR2));
0197 detectorBpr->add(std::move(rightArm));
0198
0199
0200 detectorBpr->geoIdGenerator =
0201 std::make_shared<Experimental::GeometryIdGenerator>(
0202 Experimental::GeometryIdGenerator::Config{},
0203 getDefaultLogger("RecursiveIdGenerator", Logging::VERBOSE));
0204
0205 std::cout << "Fill gaps ..." << std::endl;
0206
0207 Experimental::detail::BlueprintHelper::fillGaps(*detectorBpr);
0208 std::cout << "Filled gaps ..." << std::endl;
0209
0210 std::fstream fs("cylindrical_detector_blueprint.dot", std::ios::out);
0211 Experimental::detail::BlueprintDrawer::dotStream(fs, *detectorBpr);
0212 fs.close();
0213
0214
0215
0216
0217 auto detectorBuilder =
0218 std::make_shared<Experimental::CuboidalContainerBuilder>(
0219 *detectorBpr, Logging::VERBOSE);
0220
0221
0222 Experimental::DetectorBuilder::Config dCfg;
0223 dCfg.auxiliary = "*** Test : auto generated cuboidal detector builder ***";
0224 dCfg.name = "Cuboidal detector from blueprint";
0225 dCfg.builder = detectorBuilder;
0226 dCfg.geoIdGenerator = detectorBpr->geoIdGenerator;
0227
0228 auto detector = Experimental::DetectorBuilder(dCfg).construct(tContext);
0229
0230 BOOST_REQUIRE_NE(detector, nullptr);
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243 BOOST_CHECK_EQUAL(detector->volumes().size(), 10u);
0244 BOOST_CHECK_EQUAL(detector->volumes()[0]->name(), "leftArm_gap_0");
0245 BOOST_CHECK_EQUAL(detector->volumes()[1]->name(), "pixelL1");
0246 BOOST_CHECK_EQUAL(detector->volumes()[2]->name(), "leftArm_gap_1");
0247 BOOST_CHECK_EQUAL(detector->volumes()[3]->name(), "pixelL2");
0248 BOOST_CHECK_EQUAL(detector->volumes()[4]->name(), "leftArm_gap_2");
0249 BOOST_CHECK_EQUAL(detector->volumes()[5]->name(), "rightArm_gap_0");
0250 BOOST_CHECK_EQUAL(detector->volumes()[6]->name(), "pixelR1");
0251 BOOST_CHECK_EQUAL(detector->volumes()[7]->name(), "rightArm_gap_1");
0252 BOOST_CHECK_EQUAL(detector->volumes()[8]->name(), "pixelR2");
0253 BOOST_CHECK_EQUAL(detector->volumes()[9]->name(), "rightArm_gap_2");
0254
0255
0256
0257 double internalStretchLeftZ =
0258 detector->volumes()[0]
0259 ->volumeBounds()
0260 .values()[toUnderlying(AxisDirection::AxisZ)] +
0261 detector->volumes()[1]
0262 ->volumeBounds()
0263 .values()[toUnderlying(AxisDirection::AxisZ)] +
0264 detector->volumes()[2]
0265 ->volumeBounds()
0266 .values()[toUnderlying(AxisDirection::AxisZ)] +
0267 detector->volumes()[3]
0268 ->volumeBounds()
0269 .values()[toUnderlying(AxisDirection::AxisZ)] +
0270 detector->volumes()[4]
0271 ->volumeBounds()
0272 .values()[toUnderlying(AxisDirection::AxisZ)];
0273
0274 double internalStretchRightZ =
0275 detector->volumes()[5]
0276 ->volumeBounds()
0277 .values()[toUnderlying(AxisDirection::AxisZ)] +
0278 detector->volumes()[6]
0279 ->volumeBounds()
0280 .values()[toUnderlying(AxisDirection::AxisZ)] +
0281 detector->volumes()[7]
0282 ->volumeBounds()
0283 .values()[toUnderlying(AxisDirection::AxisZ)] +
0284 detector->volumes()[8]
0285 ->volumeBounds()
0286 .values()[toUnderlying(AxisDirection::AxisZ)] +
0287 detector->volumes()[9]
0288 ->volumeBounds()
0289 .values()[toUnderlying(AxisDirection::AxisZ)];
0290
0291 double internalStretchX1 = detector->volumes()[0]
0292 ->volumeBounds()
0293 .values()[toUnderlying(AxisDirection::AxisX)] +
0294 detector->volumes()[5]
0295 ->volumeBounds()
0296 .values()[toUnderlying(AxisDirection::AxisX)];
0297
0298 double internalStretchX2 = detector->volumes()[1]
0299 ->volumeBounds()
0300 .values()[toUnderlying(AxisDirection::AxisX)] +
0301 detector->volumes()[6]
0302 ->volumeBounds()
0303 .values()[toUnderlying(AxisDirection::AxisX)];
0304
0305 double internalStretchX3 = detector->volumes()[2]
0306 ->volumeBounds()
0307 .values()[toUnderlying(AxisDirection::AxisX)] +
0308 detector->volumes()[7]
0309 ->volumeBounds()
0310 .values()[toUnderlying(AxisDirection::AxisX)];
0311
0312 double internalStretchX4 = detector->volumes()[3]
0313 ->volumeBounds()
0314 .values()[toUnderlying(AxisDirection::AxisX)] +
0315 detector->volumes()[8]
0316 ->volumeBounds()
0317 .values()[toUnderlying(AxisDirection::AxisX)];
0318
0319 double internalStretchX5 = detector->volumes()[4]
0320 ->volumeBounds()
0321 .values()[toUnderlying(AxisDirection::AxisX)] +
0322 detector->volumes()[9]
0323 ->volumeBounds()
0324 .values()[toUnderlying(AxisDirection::AxisX)];
0325
0326 BOOST_CHECK_EQUAL(internalStretchLeftZ, detectorZ);
0327 BOOST_CHECK_EQUAL(internalStretchRightZ, detectorZ);
0328 BOOST_CHECK_EQUAL(internalStretchX1, detectorX);
0329 BOOST_CHECK_EQUAL(internalStretchX2, detectorX);
0330 BOOST_CHECK_EQUAL(internalStretchX3, detectorX);
0331 BOOST_CHECK_EQUAL(internalStretchX4, detectorX);
0332 BOOST_CHECK_EQUAL(internalStretchX5, detectorX);
0333
0334 for (auto& volume : detector->volumes()) {
0335 BOOST_CHECK_EQUAL(
0336 volume->volumeBounds().values()[toUnderlying(AxisDirection::AxisY)],
0337 detectorY);
0338 }
0339
0340
0341
0342 BOOST_CHECK_EQUAL(detector->volumes()[1]->surfaces().size(), 1u);
0343 BOOST_CHECK_EQUAL(detector->volumes()[3]->surfaces().size(), 1u);
0344 BOOST_CHECK_EQUAL(detector->volumes()[6]->surfaces().size(), 1u);
0345 BOOST_CHECK_EQUAL(detector->volumes()[8]->surfaces().size(), 1u);
0346
0347
0348
0349
0350
0351
0352
0353 std::vector<const Experimental::Portal*> portals;
0354 for (auto& volume : detector->volumes()) {
0355 portals.insert(portals.end(), volume->portals().begin(),
0356 volume->portals().end());
0357 }
0358 std::ranges::sort(portals);
0359 auto last = std::unique(portals.begin(), portals.end());
0360 portals.erase(last, portals.end());
0361 BOOST_CHECK_EQUAL(portals.size(), 19u);
0362
0363
0364
0365
0366 bool samePortalY1 = true, samePortalY2 = true;
0367 for (int i = 0; i < 4; i++) {
0368 samePortalY1 =
0369 samePortalY1 && (detector->volumes()[i]->portals().at(4) ==
0370 detector->volumes()[i + 1]->portals().at(4));
0371 samePortalY2 =
0372 samePortalY2 && (detector->volumes()[5 + i]->portals().at(4) ==
0373 detector->volumes()[5 + i + 1]->portals().at(4));
0374 }
0375 BOOST_CHECK_EQUAL(samePortalY1, true);
0376 BOOST_CHECK_EQUAL(samePortalY2, true);
0377 samePortalY1 = true, samePortalY2 = true;
0378 for (int i = 0; i < 4; i++) {
0379 samePortalY1 =
0380 samePortalY1 && (detector->volumes()[i]->portals().at(5) ==
0381 detector->volumes()[i + 1]->portals().at(5));
0382 samePortalY2 =
0383 samePortalY2 && (detector->volumes()[5 + i]->portals().at(5) ==
0384 detector->volumes()[5 + i + 1]->portals().at(5));
0385 }
0386 BOOST_CHECK_EQUAL(samePortalY1, true);
0387 BOOST_CHECK_EQUAL(samePortalY2, true);
0388
0389
0390 for (int i = 0; i < 4; i++) {
0391 bool samePortalZ1 = (detector->volumes()[i]->portals().at(1) ==
0392 detector->volumes()[i + 1]->portals().at(0));
0393 bool samePortalZ2 = (detector->volumes()[5 + i]->portals().at(1) ==
0394 detector->volumes()[5 + i + 1]->portals().at(0));
0395
0396 BOOST_CHECK_EQUAL(samePortalZ1, true);
0397 BOOST_CHECK_EQUAL(samePortalZ2, true);
0398 }
0399
0400
0401 for (int i = 0; i < 5; i++) {
0402 bool samePortalX = (detector->volumes()[i]->portals().at(3) ==
0403 detector->volumes()[5 + i]->portals().at(2));
0404 BOOST_CHECK_EQUAL(samePortalX, true);
0405 }
0406 }
0407
0408 BOOST_AUTO_TEST_SUITE_END()
0409
0410 }