Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Geant4ConvertersTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Geant4ConvertersTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2022 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include <boost/test/unit_test.hpp>
10 
24 
25 #include <array>
26 #include <cmath>
27 #include <memory>
28 #include <stdexcept>
29 #include <tuple>
30 
31 #include "G4Box.hh"
32 #include "G4LogicalVolume.hh"
33 #include "G4Material.hh"
34 #include "G4PVPlacement.hh"
35 #include "G4RotationMatrix.hh"
36 #include "G4SystemOfUnits.hh"
37 #include "G4ThreeVector.hh"
38 #include "G4Trd.hh"
39 #include "G4Tubs.hh"
40 #include "G4VPhysicalVolume.hh"
41 
43 
45 G4Material* g4Material = new G4Material("Material", 6., 12., rho);
46 
47 BOOST_AUTO_TEST_SUITE(Geant4Plugin)
48 
49 BOOST_AUTO_TEST_CASE(Geant4AlgebraConversion) {
50  G4ThreeVector g4Translation(10., 20., 30.);
51 
52  auto translated = Acts::Geant4AlgebraConverter{}.transform(g4Translation);
53  auto actsTranslation = translated.translation();
54  BOOST_CHECK(actsTranslation[0] == 10.);
55  BOOST_CHECK(actsTranslation[1] == 20.);
56  BOOST_CHECK(actsTranslation[2] == 30.);
57 
58  auto translatedScaled =
59  Acts::Geant4AlgebraConverter{10.}.transform(g4Translation);
60  auto actsTranslationScaled = translatedScaled.translation();
61  BOOST_CHECK(actsTranslationScaled[0] == 100.);
62  BOOST_CHECK(actsTranslationScaled[1] == 200.);
63  BOOST_CHECK(actsTranslationScaled[2] == 300.);
64 }
65 
66 BOOST_AUTO_TEST_CASE(Geant4CylinderConversion) {
67  G4Tubs cylinder("Cylinder", 399., 401., 800., -M_PI * CLHEP::radian,
68  2 * M_PI * CLHEP::radian);
69  auto [bounds, thickness] =
72  10e-10);
73  CHECK_CLOSE_ABS(bounds->get(Acts::CylinderBounds::BoundValues::eHalfLengthZ),
74  800., 10e-10);
76  bounds->get(Acts::CylinderBounds::BoundValues::eHalfPhiSector), M_PI,
77  10e-10);
78  CHECK_CLOSE_ABS(bounds->get(Acts::CylinderBounds::BoundValues::eAveragePhi),
79  0., 10e-10);
80  CHECK_CLOSE_ABS(thickness, 2., 10e-10);
81 }
82 
83 BOOST_AUTO_TEST_CASE(Geant4RadialConversion) {
84  G4Tubs disc("disc", 40., 400., 2., -M_PI * CLHEP::radian,
85  2 * M_PI * CLHEP::radian);
87  CHECK_CLOSE_ABS(bounds->get(Acts::RadialBounds::BoundValues::eMinR), 40.,
88  10e-10);
89  CHECK_CLOSE_ABS(bounds->get(Acts::RadialBounds::BoundValues::eMaxR), 400.,
90  10e-10);
91  CHECK_CLOSE_ABS(bounds->get(Acts::RadialBounds::BoundValues::eHalfPhiSector),
92  M_PI, 10e-10);
93  CHECK_CLOSE_ABS(bounds->get(Acts::RadialBounds::BoundValues::eAveragePhi), 0.,
94  10e-10);
95  CHECK_CLOSE_ABS(thickness, 4., 10e-10);
96 }
97 
98 BOOST_AUTO_TEST_CASE(Geant4LineConversion) {
99  G4Tubs line("line", 0., 20., 400., 0., 2 * M_PI);
102  CHECK_CLOSE_ABS(bounds->get(Acts::LineBounds::BoundValues::eHalfLengthZ),
103  400., 10e-10);
104 }
105 
106 BOOST_AUTO_TEST_CASE(Geant4BoxConversion) {
107  // Test the standard orientations
108  G4Box sensorXY("SensorXY", 23., 34., 1.);
109  auto [boundsXY, axesXY, thicknessZ] =
111  CHECK_CLOSE_ABS(boundsXY->halfLengthX(), 23., 10e-10);
112  CHECK_CLOSE_ABS(boundsXY->halfLengthY(), 34., 10e-10);
113  auto refXY = std::array<int, 2u>{0, 1};
114  BOOST_CHECK(axesXY == refXY);
115  CHECK_CLOSE_ABS(thicknessZ, 2., 10e-10);
116 
117  G4Box sensorYZ("SensorYZ", 2., 45., 56.);
118  auto [boundsYZ, axesYZ, thicknessX] =
120  CHECK_CLOSE_ABS(boundsYZ->halfLengthX(), 45., 10e-10);
121  CHECK_CLOSE_ABS(boundsYZ->halfLengthY(), 56., 10e-10);
122  auto refYZ = std::array<int, 2u>{1, 2};
123  BOOST_CHECK(axesYZ == refYZ);
124  CHECK_CLOSE_ABS(thicknessX, 4., 10e-10);
125 
126  G4Box sensorZX("SensorZX", 78., 2., 67.);
127  auto [boundsZX, axesZX, thicknessY] =
129  CHECK_CLOSE_ABS(boundsZX->halfLengthX(), 67., 10e-10);
130  CHECK_CLOSE_ABS(boundsZX->halfLengthY(), 78., 10e-10);
131  auto refZX = std::array<int, 2u>{2, 0};
132  BOOST_CHECK(axesZX == refZX);
133  CHECK_CLOSE_ABS(thicknessY, 4., 10e-10);
134 
135  // Test the flipped axis
136  G4Box sensorXz("SensorXz", 78., 2., 67.);
137  auto [boundsXz, axesXz, thicknessY2] =
138  Acts::Geant4ShapeConverter{1, true}.rectangleBounds(sensorXz);
139  CHECK_CLOSE_ABS(boundsXz->halfLengthX(), 78., 10e-10);
140  CHECK_CLOSE_ABS(boundsXz->halfLengthY(), 67., 10e-10);
141  auto refXz = std::array<int, 2u>{0, -2};
142  BOOST_CHECK(axesXz == refXz);
143  CHECK_CLOSE_ABS(thicknessY2, 4., 10e-10);
144 }
145 
146 BOOST_AUTO_TEST_CASE(Geant4TrapzoidConversion) {
147  // Standard TRD: XY are already well defined
148  G4Trd trdXY("trdXY", 100, 150, 200, 200, 2);
149  auto [boundsXY, axesXY, thicknessZ] =
152  boundsXY->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXnegY), 100,
153  10e-10);
155  boundsXY->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXposY), 150,
156  10e-10);
158  boundsXY->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthY), 200,
159  10e-10);
160  auto refXY = std::array<int, 2u>{0, 1};
161  BOOST_CHECK(axesXY == refXY);
162  CHECK_CLOSE_ABS(thicknessZ, 4., 10e-10);
163 
164  // Flipped, yX are the coordinates
165  G4Trd trdyX("trdyX", 200, 200, 100, 150, 2);
166  auto [boundsyX, axesyX, thicknessZ2] =
169  boundsyX->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXnegY), 100,
170  10e-10);
172  boundsyX->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXposY), 150,
173  10e-10);
175  boundsyX->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthY), 200,
176  10e-10);
177  auto refyX = std::array<int, 2u>{-1, 0};
178  BOOST_CHECK(axesyX == refyX);
179  CHECK_CLOSE_ABS(thicknessZ2, 4., 10e-10);
180 
181  // YZ span the trapezoid
182  G4Trd trdYZ("trdYZ", 2, 2, 120, 140, 200);
183  auto [boundsYZ, axesYZ, thicknessX] =
186  boundsYZ->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXnegY), 120.,
187  10e-10);
189  boundsYZ->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXposY), 140.,
190  10e-10);
192  boundsYZ->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthY), 200.,
193  10e-10);
194  auto refYZ = std::array<int, 2u>{1, 2};
195  BOOST_CHECK(axesYZ == refYZ);
196  CHECK_CLOSE_ABS(thicknessX, 4., 10e-10);
197 
198  // Xz span the trapezoid
199  G4Trd trdXz("trdXz", 50, 75, 1, 1, 200);
200  auto [boundsXz, axesXz, thicknessY] =
203  boundsXz->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXnegY), 50.,
204  10e-10);
206  boundsXz->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthXposY), 75.,
207  10e-10);
209  boundsXz->get(Acts::TrapezoidBounds::BoundValues::eHalfLengthY), 200.,
210  10e-10);
211  auto refXz = std::array<int, 2u>{0, -2};
212  BOOST_CHECK(axesXz == refXz);
213  CHECK_CLOSE_ABS(thicknessY, 2., 10e-10);
214 }
215 
216 BOOST_AUTO_TEST_CASE(Geant4PlanarConversion) {
217  G4Box boxXY("boxXY", 23., 34., 1.);
218  auto pBoundsBox =
219  std::get<0u>(Acts::Geant4ShapeConverter{}.planarBounds(boxXY));
220  auto rBounds = dynamic_cast<const Acts::RectangleBounds*>(pBoundsBox.get());
221  BOOST_CHECK(rBounds != nullptr);
222 
223  G4Trd trdXY("trdXY", 100, 150, 200, 200, 2);
224  auto pBoundsTrd =
225  std::get<0u>(Acts::Geant4ShapeConverter{}.planarBounds(trdXY));
226  auto tBounds = dynamic_cast<const Acts::TrapezoidBounds*>(pBoundsTrd.get());
227  BOOST_CHECK(tBounds != nullptr);
228 }
229 
230 BOOST_AUTO_TEST_CASE(Geant4BoxVPhysConversion) {
232 
233  G4Box* g4Box = new G4Box("Box", 23., 34., 0.5 * thickness);
234  G4RotationMatrix* g4Rot = new G4RotationMatrix({0., 0., 1.}, 1.2);
235  G4LogicalVolume* g4BoxLog = new G4LogicalVolume(g4Box, g4Material, "BoxLog");
236 
237  G4ThreeVector g4Trans(0., 0., 100.);
238  G4PVPlacement g4BoxPhys(g4Rot, g4Trans, g4BoxLog, "BoxPhys", nullptr, false,
239  1);
240 
241  auto planeSurface = Acts::Geant4PhysicalVolumeConverter{}.surface(
242  g4BoxPhys, Acts::Transform3::Identity(), true, thickness);
243  BOOST_CHECK(planeSurface != nullptr);
244  BOOST_CHECK(planeSurface->type() == Acts::Surface::SurfaceType::Plane);
245 
246  auto material = planeSurface->surfaceMaterial();
247  BOOST_CHECK(material != nullptr);
248 
249  auto materialSlab = material->materialSlab(Acts::Vector3{0., 0., 0.});
250  // Here it should be uncompressed material
251  CHECK_CLOSE_ABS(materialSlab.material().massDensity(), rho, 0.001);
252  CHECK_CLOSE_REL(thickness / g4Material->GetRadlen(),
253  materialSlab.thicknessInX0(), 0.1);
254 
255  // Convert with compression
256  Acts::ActsScalar compression = 4.;
258  g4BoxPhys, Acts::Transform3::Identity(), true, thickness / compression);
259  BOOST_CHECK(planeSurface != nullptr);
260  BOOST_CHECK(planeSurface->type() == Acts::Surface::SurfaceType::Plane);
261 
262  material = planeSurface->surfaceMaterial();
263  BOOST_CHECK(material != nullptr);
264  materialSlab = material->materialSlab(Acts::Vector3{0., 0., 0.});
265 
266  // Here it should be uncompressed material
267  CHECK_CLOSE_ABS(materialSlab.material().massDensity(), compression * rho,
268  0.001);
269  CHECK_CLOSE_REL(thickness / g4Material->GetRadlen(),
270  materialSlab.thicknessInX0(), 0.01);
271 
272  CHECK_CLOSE_ABS(materialSlab.thickness(), thickness / compression, 0.01);
273  CHECK_CLOSE_REL(materialSlab.material().X0() * compression,
274  g4Material->GetRadlen(), 0.01);
275 
276  delete g4Box;
277  delete g4Rot;
278  delete g4BoxLog;
279 }
280 
281 BOOST_AUTO_TEST_CASE(Geant4CylVPhysConversion) {
282  Acts::ActsScalar radius = 45.;
284  Acts::ActsScalar halfLengthZ = 200;
285 
286  G4Tubs* g4Tube = new G4Tubs("Tube", radius, radius + thickness, halfLengthZ,
287  -M_PI * CLHEP::radian, 2 * M_PI * CLHEP::radian);
288 
289  G4RotationMatrix* g4Rot = new G4RotationMatrix({0., 0., 1.}, 0.);
290  G4LogicalVolume* g4TubeLog =
291  new G4LogicalVolume(g4Tube, g4Material, "TubeLog");
292  G4ThreeVector g4Trans(0., 0., 100.);
293  G4PVPlacement g4CylinderPhys(g4Rot, g4Trans, g4TubeLog, "TubePhys", nullptr,
294  false, 1);
295 
296  auto cylinderSurface = Acts::Geant4PhysicalVolumeConverter{}.surface(
297  g4CylinderPhys, Acts::Transform3::Identity(), true, thickness);
298  BOOST_CHECK(cylinderSurface != nullptr);
299  BOOST_CHECK(cylinderSurface->type() == Acts::Surface::SurfaceType::Cylinder);
300 
301  auto material = cylinderSurface->surfaceMaterial();
302  BOOST_CHECK(material != nullptr);
303 
304  auto materialSlab = material->materialSlab(Acts::Vector3{0., 0., 0.});
305  CHECK_CLOSE_REL(thickness / g4Material->GetRadlen(),
306  materialSlab.thicknessInX0(), 0.1);
307 
308  // Here it should be uncompressed material
309  CHECK_CLOSE_ABS(materialSlab.material().massDensity(), rho, 0.001);
310 
312  BOOST_CHECK_THROW(
313  Acts::Geant4PhysicalVolumeConverter{Acts::Surface::SurfaceType::Plane}
314  .surface(g4CylinderPhys, Acts::Transform3::Identity(), true,
315  thickness),
316  std::runtime_error);
317 
318  delete g4Tube;
319  delete g4Rot;
320  delete g4TubeLog;
321 }
322 
323 BOOST_AUTO_TEST_CASE(Geant4VDiscVPhysConversion) {
324  Acts::ActsScalar innerRadius = 45.;
325  Acts::ActsScalar outerRadius = 75.;
327 
328  G4Tubs* g4Tube = new G4Tubs("Disc", innerRadius, outerRadius, 0.5 * thickness,
329  -M_PI * CLHEP::radian, 2 * M_PI * CLHEP::radian);
330 
331  G4RotationMatrix* g4Rot = new G4RotationMatrix({0., 0., 1.}, 0.);
332  G4LogicalVolume* g4TubeLog =
333  new G4LogicalVolume(g4Tube, g4Material, "TubeLog");
334  G4ThreeVector g4Trans(0., 0., 100.);
335  G4PVPlacement g4discPhys(g4Rot, g4Trans, g4TubeLog, "TubePhys", nullptr,
336  false, 1);
337 
338  auto discSurface = Acts::Geant4PhysicalVolumeConverter{}.surface(
339  g4discPhys, Acts::Transform3::Identity(), true, thickness);
340  BOOST_CHECK(discSurface != nullptr);
341  BOOST_CHECK(discSurface->type() == Acts::Surface::SurfaceType::Disc);
342 
343  auto material = discSurface->surfaceMaterial();
344  BOOST_CHECK(material != nullptr);
345 
346  auto materialSlab = material->materialSlab(Acts::Vector3{0., 0., 0.});
347  // Here it should be uncompressed material
348  CHECK_CLOSE_ABS(materialSlab.material().massDensity(), rho, 0.001);
349 
350  delete g4Tube;
351  delete g4Rot;
352  delete g4TubeLog;
353 }
354 
355 BOOST_AUTO_TEST_CASE(Geant4LineVPhysConversion) {
356  Acts::ActsScalar innerRadius = 0.;
357  Acts::ActsScalar outerRadius = 20.;
359 
360  G4Tubs* g4Tube = new G4Tubs("Line", innerRadius, outerRadius, 0.5 * thickness,
361  -M_PI * CLHEP::radian, 2 * M_PI * CLHEP::radian);
362 
363  G4RotationMatrix* g4Rot = new G4RotationMatrix({0., 0., 1.}, 0.);
364  G4LogicalVolume* g4TubeLog =
365  new G4LogicalVolume(g4Tube, g4Material, "LineLog");
366  G4ThreeVector g4Trans(0., 0., 100.);
367  G4PVPlacement g4linePhys(g4Rot, g4Trans, g4TubeLog, "LinePhys", nullptr,
368  false, 1);
369 
370  auto lineSurface =
371  Acts::Geant4PhysicalVolumeConverter{Acts::Surface::SurfaceType::Straw}
372  .surface(g4linePhys, Acts::Transform3::Identity(), true, thickness);
373  BOOST_CHECK(lineSurface != nullptr);
374  BOOST_CHECK(lineSurface->type() == Acts::Surface::SurfaceType::Straw);
375 
376  delete g4Tube;
377  delete g4Rot;
378  delete g4TubeLog;
379 }
380 
381 BOOST_AUTO_TEST_SUITE_END()