File indexing completed on 2025-07-14 08:12:34
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Plugins/Geant4/Geant4DetectorSurfaceFactory.hpp"
0012 #include "Acts/Plugins/Geant4/Geant4PhysicalVolumeSelectors.hpp"
0013 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0014 #include "Acts/Visualization/GeometryView3D.hpp"
0015 #include "Acts/Visualization/ObjVisualization3D.hpp"
0016
0017 #include <memory>
0018 #include <numbers>
0019 #include <string>
0020
0021 #include "G4Box.hh"
0022 #include "G4LogicalVolume.hh"
0023 #include "G4PVPlacement.hh"
0024 #include "G4RotationMatrix.hh"
0025 #include "G4SystemOfUnits.hh"
0026 #include "G4ThreeVector.hh"
0027 #include "G4Transform3D.hh"
0028 #include "G4Tubs.hh"
0029
0030 class G4VPhysicalVolume;
0031
0032 BOOST_AUTO_TEST_SUITE(Geant4Plugin)
0033
0034 BOOST_AUTO_TEST_CASE(Geant4DetecturSurfaceFactory_box) {
0035 G4Box* worldS = new G4Box("world", 100, 100, 100);
0036
0037 G4LogicalVolume* worldLV = new G4LogicalVolume(worldS, nullptr, "World");
0038
0039 G4Box* boxS = new G4Box("box", 10, 20, 20);
0040 G4LogicalVolume* boxLV = new G4LogicalVolume(boxS, nullptr, "World");
0041 G4VPhysicalVolume* boxPV = new G4PVPlacement(nullptr, G4ThreeVector(), boxLV,
0042 "Box", worldLV, false, 0, true);
0043
0044 G4Transform3D nominal;
0045
0046
0047 auto nameSelector =
0048 std::make_shared<Acts::Geant4PhysicalVolumeSelectors::NameSelector>(
0049 std::vector<std::string>{"ox"}, false);
0050
0051 Acts::Geant4DetectorSurfaceFactory::Cache cache;
0052 Acts::Geant4DetectorSurfaceFactory::Options options;
0053 options.sensitiveSurfaceSelector = nameSelector;
0054
0055 Acts::Geant4DetectorSurfaceFactory::Config factoryConfig;
0056 Acts::Geant4DetectorSurfaceFactory factory(factoryConfig);
0057
0058 factory.construct(cache, nominal, *boxPV, options);
0059
0060 BOOST_CHECK_EQUAL(cache.sensitiveSurfaces.size(), 1u);
0061 BOOST_CHECK_EQUAL(cache.passiveSurfaces.size(), 0u);
0062
0063 auto [element, surface] = cache.sensitiveSurfaces.front();
0064 BOOST_CHECK_EQUAL(surface->type(), Acts::Surface::SurfaceType::Plane);
0065 }
0066
0067 BOOST_AUTO_TEST_CASE(Geant4DetecturSurfaceFactory_Cylinder) {
0068 G4Box* worldS = new G4Box("world", 1000, 1000, 1000);
0069
0070 G4LogicalVolume* worldLV = new G4LogicalVolume(worldS, nullptr, "World");
0071
0072 G4Tubs* cylinderS =
0073 new G4Tubs("cylinder", 99, 100, 100, -std::numbers::pi * CLHEP::radian,
0074 2 * std::numbers::pi * CLHEP::radian);
0075
0076 G4LogicalVolume* cylinderLV =
0077 new G4LogicalVolume(cylinderS, nullptr, "World");
0078 G4VPhysicalVolume* cylinderPV =
0079 new G4PVPlacement(nullptr, G4ThreeVector(), cylinderLV, "Cylinder",
0080 worldLV, false, 0, true);
0081
0082 G4Transform3D nominal;
0083
0084
0085 auto nameSelector =
0086 std::make_shared<Acts::Geant4PhysicalVolumeSelectors::NameSelector>(
0087 std::vector<std::string>{"yl"}, false);
0088
0089 Acts::Geant4DetectorSurfaceFactory::Cache cache;
0090 Acts::Geant4DetectorSurfaceFactory::Options options;
0091 options.sensitiveSurfaceSelector = nameSelector;
0092
0093 Acts::Geant4DetectorSurfaceFactory::Config factoryConfig;
0094 Acts::Geant4DetectorSurfaceFactory factory(factoryConfig);
0095 factory.construct(cache, nominal, *cylinderPV, options);
0096
0097 BOOST_CHECK_EQUAL(cache.sensitiveSurfaces.size(), 1u);
0098 BOOST_CHECK_EQUAL(cache.passiveSurfaces.size(), 0u);
0099
0100 auto [element, surface] = cache.sensitiveSurfaces.front();
0101 BOOST_CHECK_EQUAL(surface->type(), Acts::Surface::SurfaceType::Cylinder);
0102 }
0103
0104 BOOST_AUTO_TEST_CASE(Geant4DetecturSurfaceFactory_Transforms) {
0105 Acts::GeometryContext gctx;
0106
0107 G4Box* worldS = new G4Box("world", 1000, 1000, 1000);
0108 G4LogicalVolume* worldLV = new G4LogicalVolume(worldS, nullptr, "World");
0109 G4VPhysicalVolume* worldPV = new G4PVPlacement(
0110 nullptr, G4ThreeVector(), worldLV, "World", nullptr, false, 0, false);
0111
0112 auto vol1S = new G4Box("volume1", 25, 10, 50);
0113 auto vol1L = new G4LogicalVolume(vol1S, nullptr, "Volume1");
0114
0115 G4Transform3D transformVol1(CLHEP::HepRotationX(std::numbers::pi / 4.),
0116 G4ThreeVector(20, 0, 0));
0117
0118 [[maybe_unused]] auto vol1PV = new G4PVPlacement(
0119 transformVol1, vol1L, "Volume1", worldLV, false, 0, false);
0120
0121 auto vol2S = new G4Box("volume2", 25, 10, 50);
0122 auto vol2L = new G4LogicalVolume(vol2S, nullptr, "Volume2");
0123
0124 G4Transform3D transformVol2(CLHEP::HepRotationY(std::numbers::pi / 6.),
0125 G4ThreeVector(0, 100, 20));
0126
0127 [[maybe_unused]] auto vol2PV = new G4PVPlacement(
0128 transformVol2, vol2L, "Volume2", vol1L, false, 0, false);
0129
0130 auto vol3S = new G4Box("volume3", 25, 10, 50);
0131 auto vol3L = new G4LogicalVolume(vol3S, nullptr, "Volume3");
0132
0133 G4Transform3D transformVol3(CLHEP::HepRotationZ(std::numbers::pi / 12.),
0134 G4ThreeVector(30, 100, 0));
0135
0136 [[maybe_unused]] auto vol3PV = new G4PVPlacement(
0137 transformVol3, vol3L, "Volume3", vol2L, false, 0, false);
0138
0139
0140 auto nameSelector =
0141 std::make_shared<Acts::Geant4PhysicalVolumeSelectors::NameSelector>(
0142 std::vector<std::string>{"olume"}, false);
0143
0144 Acts::Geant4DetectorSurfaceFactory::Cache cache;
0145 Acts::Geant4DetectorSurfaceFactory::Options options;
0146 options.sensitiveSurfaceSelector = nameSelector;
0147
0148 G4Transform3D nominal;
0149
0150 Acts::Geant4DetectorSurfaceFactory::Config factoryConfig;
0151 Acts::Geant4DetectorSurfaceFactory factory(factoryConfig);
0152 factory.construct(cache, nominal, *worldPV, options);
0153
0154 auto [element, surface] = cache.sensitiveSurfaces.front();
0155 BOOST_CHECK_EQUAL(surface->type(), Acts::Surface::SurfaceType::Plane);
0156
0157 auto center = surface->center(gctx);
0158 auto normal = surface->normal(gctx, center, Acts::Vector3(1, 0, 0));
0159
0160
0161
0162
0163
0164
0165
0166
0167 CHECK_CLOSE_ABS(center.x(), 45.981, 1e-3);
0168 CHECK_CLOSE_ABS(center.y(), 137.886, 1e-3);
0169 CHECK_CLOSE_ABS(center.z(), 144.957, 1e-3);
0170
0171 CHECK_CLOSE_ABS(normal.x(), 0.5, 1e-3);
0172 CHECK_CLOSE_ABS(normal.y(), -0.612372, 1e-3);
0173 CHECK_CLOSE_ABS(normal.z(), 0.612372, 1e-3);
0174
0175 Acts::ObjVisualization3D obj;
0176 Acts::Vector3 origin(0, 0, 0);
0177 Acts::GeometryView3D::drawArrowForward(obj, origin, Acts::Vector3(100, 0, 0),
0178 1000, 10, {.color = {255, 0, 0}});
0179 Acts::GeometryView3D::drawArrowForward(obj, origin, Acts::Vector3(0, 100, 0),
0180 1000, 10, {.color = {0, 255, 0}});
0181 Acts::GeometryView3D::drawArrowForward(obj, origin, Acts::Vector3(0, 0, 100),
0182 1000, 10, {.color = {0, 0, 255}});
0183 Acts::GeometryView3D::drawArrowForward(obj, surface->center(gctx),
0184 surface->center(gctx) + 100 * normal,
0185 1000, 10, {.color = {0, 255, 0}});
0186 auto surfaces = cache.sensitiveSurfaces;
0187 for (const auto& [k, val] : Acts::enumerate(cache.sensitiveSurfaces)) {
0188 const auto& [el, surf] = val;
0189 Acts::ViewConfig vCfg;
0190 if (k == 0) {
0191 vCfg.color = {0, 255, 0};
0192 } else if (k == 1) {
0193 vCfg.color = {255, 0, 0};
0194 } else if (k == 2) {
0195 vCfg.color = {0, 255, 255};
0196 }
0197 Acts::GeometryView3D::drawSurface(obj, *surf, gctx,
0198 Acts::Transform3::Identity(), vCfg);
0199 }
0200
0201 obj.write("RotatedSurface.obj");
0202 }
0203
0204 BOOST_AUTO_TEST_CASE(Geant4DetecturSurfaceFactory_elemnet_overwrite) {
0205
0206
0207
0208
0209 class ExtendedGeant4DetectorElement : public Acts::Geant4DetectorElement {
0210 public:
0211 using Acts::Geant4DetectorElement::Geant4DetectorElement;
0212
0213 double thickness() const final {
0214
0215 return 42.0;
0216 }
0217 };
0218
0219
0220 auto extendedElementFactory =
0221 [](std::shared_ptr<Acts::Surface> surface,
0222 const G4VPhysicalVolume& g4physVol, const Acts::Transform3& toGlobal,
0223 double thickness) -> std::shared_ptr<Acts::Geant4DetectorElement> {
0224 return std::make_shared<ExtendedGeant4DetectorElement>(
0225 std::move(surface), g4physVol, toGlobal, thickness);
0226 };
0227
0228 G4Box* worldS = new G4Box("world", 100, 100, 100);
0229 G4LogicalVolume* worldLV = new G4LogicalVolume(worldS, nullptr, "World");
0230
0231 G4Box* boxS = new G4Box("box", 10, 20, 20);
0232 G4LogicalVolume* boxLV = new G4LogicalVolume(boxS, nullptr, "World");
0233 G4VPhysicalVolume* boxPV = new G4PVPlacement(nullptr, G4ThreeVector(), boxLV,
0234 "Box", worldLV, false, 0, true);
0235
0236 G4Transform3D nominal;
0237
0238
0239 auto nameSelector =
0240 std::make_shared<Acts::Geant4PhysicalVolumeSelectors::NameSelector>(
0241 std::vector<std::string>{"ox"}, false);
0242
0243 Acts::Geant4DetectorSurfaceFactory::Cache cache;
0244 Acts::Geant4DetectorSurfaceFactory::Options options;
0245 options.sensitiveSurfaceSelector = nameSelector;
0246
0247 Acts::Geant4DetectorSurfaceFactory::Config config;
0248 config.detectorElementFactory = extendedElementFactory;
0249 Acts::Geant4DetectorSurfaceFactory factory(config);
0250 factory.construct(cache, nominal, *boxPV, options);
0251
0252 BOOST_CHECK_EQUAL(cache.sensitiveSurfaces.size(), 1u);
0253 BOOST_CHECK_EQUAL(cache.passiveSurfaces.size(), 0u);
0254
0255 auto [element, surface] = cache.sensitiveSurfaces.front();
0256 BOOST_CHECK_EQUAL(surface->type(), Acts::Surface::SurfaceType::Plane);
0257
0258
0259 CHECK_CLOSE_ABS(element->thickness(), 42.0, 1e-6);
0260 }
0261
0262 BOOST_AUTO_TEST_SUITE_END()