Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BlueprintHelperTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file BlueprintHelperTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2023 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 
13 
14 #include <exception>
15 #include <fstream>
16 
17 namespace Acts {
18 namespace Experimental {
19 class IInternalStructureBuilder {};
20 } // namespace Experimental
21 } // namespace Acts
22 
23 BOOST_AUTO_TEST_SUITE(Experimental)
24 
25 BOOST_AUTO_TEST_CASE(BlueprintHelperSorting) {
26  // Create root node
27  std::vector<Acts::BinningValue> detectorBinning = {Acts::binR};
28  std::vector<Acts::ActsScalar> detectorBoundaries = {0., 50., 100.};
29  auto detector = std::make_unique<Acts::Experimental::Blueprint::Node>(
30  "detector", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
31  detectorBoundaries, detectorBinning);
32 
33  BOOST_CHECK(detector->parent == nullptr);
34  BOOST_CHECK(detector->children.empty());
35  BOOST_CHECK(detector->name == "detector");
36 
37  std::vector<Acts::BinningValue> pixelsBinning = {Acts::binZ};
38  std::vector<Acts::ActsScalar> pixelsBoundaries = {20., 50., 100.};
39 
40  auto pixels = std::make_unique<Acts::Experimental::Blueprint::Node>(
41  "pixels", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
42  pixelsBoundaries, pixelsBinning);
43 
44  std::vector<Acts::ActsScalar> beamPipeBoundaries = {0., 20., 100.};
45  auto beamPipe = std::make_unique<Acts::Experimental::Blueprint::Node>(
46  "beam_pipe", Acts::Transform3::Identity(), Acts::VolumeBounds::eOther,
47  beamPipeBoundaries);
48 
49  std::vector<Acts::ActsScalar> gapBoundaries = {20., 50., 10.};
50  auto gap0 = std::make_unique<Acts::Experimental::Blueprint::Node>(
51  "gap0", Acts::Transform3::Identity() * Acts::Translation3(0., 0., -90.),
52  Acts::VolumeBounds::eCylinder, gapBoundaries);
53 
54  std::vector<Acts::ActsScalar> layerBoundaries = {20., 50., 80.};
55  auto layer = std::make_unique<Acts::Experimental::Blueprint::Node>(
56  "layer", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
57  layerBoundaries,
58  std::make_shared<Acts::Experimental::IInternalStructureBuilder>());
59 
60  auto gap1 = std::make_unique<Acts::Experimental::Blueprint::Node>(
61  "gap1", Acts::Transform3::Identity() * Acts::Translation3(0., 0., 90.),
62  Acts::VolumeBounds::eCylinder, gapBoundaries);
63 
64  // Add the nodes in a random fashion
65  pixels->add(std::move(gap1));
66  pixels->add(std::move(gap0));
67  pixels->add(std::move(layer));
68  // Add pixels and beam pipe in reverse order
69  detector->add(std::move(pixels));
70  detector->add(std::move(beamPipe));
71 
72  std::ofstream fs("detector_unordered.dot");
73  detector->dotStream(fs);
74  fs.close();
75 
76  // Sort the detector
78 
79  // Test the recursive sort worked
80  BOOST_CHECK(detector->children.front()->name == "beam_pipe");
81  BOOST_CHECK(detector->children.back()->name == "pixels");
82  BOOST_CHECK(detector->children.back()->children.front()->name == "gap0");
83  BOOST_CHECK(detector->children.back()->children[1u]->name == "layer");
84  BOOST_CHECK(detector->children.back()->children.back()->name == "gap1");
85 
86  std::ofstream fs2("detector_ordered.dot");
87  detector->dotStream(fs2);
88  fs2.close();
89 }
90 
91 BOOST_AUTO_TEST_CASE(BlueprintCylindricalGapFilling) {
92  // Detector dimensions
93  Acts::ActsScalar detectorIr = 0.;
94  Acts::ActsScalar detectorOr = 120.;
95  Acts::ActsScalar detectorHz = 400.;
96 
97  // Beam pipe
98  Acts::ActsScalar beamPipeOr = 20.;
99 
100  // Pixel system
101  Acts::ActsScalar pixelIr = 25;
102  Acts::ActsScalar pixelOr = 115;
103  Acts::ActsScalar pixelEcHz = 50;
104 
105  auto innerBuilder =
106  std::make_shared<Acts::Experimental::IInternalStructureBuilder>();
107 
108  // Create root node
109  std::vector<Acts::BinningValue> detectorBinning = {Acts::binR};
110  std::vector<Acts::ActsScalar> detectorBoundaries = {detectorIr, detectorOr,
111  detectorHz};
112 
113  // The root node - detector
114  auto detector = std::make_unique<Acts::Experimental::Blueprint::Node>(
115  "detector", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
116  detectorBoundaries, detectorBinning);
117 
118  // The beam pipe
119  std::vector<Acts::ActsScalar> beamPipeBoundaries = {detectorIr, beamPipeOr,
120  detectorHz};
121  auto beamPipe = std::make_unique<Acts::Experimental::Blueprint::Node>(
122  "beam_pipe", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
123  beamPipeBoundaries, innerBuilder);
124  detector->add(std::move(beamPipe));
125 
126  // A pixel system
127  std::vector<Acts::ActsScalar> pixelBoundaries = {pixelIr, pixelOr,
128  detectorHz};
129  std::vector<Acts::BinningValue> pixelBinning = {Acts::binZ};
130  auto pixel = std::make_unique<Acts::Experimental::Blueprint::Node>(
131  "pixel", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
132  pixelBoundaries, pixelBinning);
133 
134  // Nec: Small differences to check if the adjustments are made
135  std::vector<Acts::ActsScalar> pixelEcBoundaries = {pixelIr, pixelOr - 5.,
136  pixelEcHz};
137  std::vector<Acts::BinningValue> pixelEcBinning = {Acts::binZ};
138 
139  auto pixelNec = std::make_unique<Acts::Experimental::Blueprint::Node>(
140  "pixelNec",
141  Acts::Transform3::Identity() *
142  Acts::Translation3(0., 0., -detectorHz + pixelEcHz),
143  Acts::VolumeBounds::eCylinder, pixelEcBoundaries, pixelEcBinning);
144 
145  // Add a single encap layer
146  std::vector<Acts::ActsScalar> pixelNecBoundaries = {pixelIr + 2, pixelOr - 7.,
147  10.};
148  auto pixelNecLayer = std::make_unique<Acts::Experimental::Blueprint::Node>(
149  "pixelNecLayer",
150  Acts::Transform3::Identity() *
151  Acts::Translation3(0., 0., -detectorHz + pixelEcHz),
152  Acts::VolumeBounds::eCylinder, pixelNecBoundaries, innerBuilder);
153 
154  pixelNec->add(std::move(pixelNecLayer));
155 
156  // Barrel
157  std::vector<Acts::ActsScalar> pixelBarrelBoundaries = {
158  pixelIr + 1, pixelOr - 1., detectorHz - 2 * pixelEcHz};
159  std::vector<Acts::BinningValue> pixelBarrelBinning = {Acts::binR};
160 
161  auto pixelBarrel = std::make_unique<Acts::Experimental::Blueprint::Node>(
162  "pixelBarrel", Acts::Transform3::Identity(),
163  Acts::VolumeBounds::eCylinder, pixelBarrelBoundaries, pixelBarrelBinning);
164 
165  std::vector<Acts::ActsScalar> pixelBarrelL0Boundaries = {
166  60, 65., detectorHz - 2 * pixelEcHz};
167  auto pixelBarrelL0 = std::make_unique<Acts::Experimental::Blueprint::Node>(
168  "pixelBarrelL0", Acts::Transform3::Identity(),
169  Acts::VolumeBounds::eCylinder, pixelBarrelL0Boundaries, innerBuilder);
170 
171  std::vector<Acts::ActsScalar> pixelBarrelL1Boundaries = {
172  100, 105., detectorHz - 2 * pixelEcHz};
173  auto pixelBarrelL1 = std::make_unique<Acts::Experimental::Blueprint::Node>(
174  "pixelBarrelL1", Acts::Transform3::Identity(),
175  Acts::VolumeBounds::eCylinder, pixelBarrelL1Boundaries, innerBuilder);
176  pixelBarrel->add(std::move(pixelBarrelL0));
177  pixelBarrel->add(std::move(pixelBarrelL1));
178 
179  auto pixelPec = std::make_unique<Acts::Experimental::Blueprint::Node>(
180  "pixelPec",
181  Acts::Transform3::Identity() *
182  Acts::Translation3(0., 0., +detectorHz - pixelEcHz),
183  Acts::VolumeBounds::eCylinder, pixelEcBoundaries, pixelEcBinning);
184 
185  std::vector<Acts::ActsScalar> pixelPecBoundaries = {pixelIr + 2, pixelOr - 7.,
186  10.};
187  auto pixelPecLayer = std::make_unique<Acts::Experimental::Blueprint::Node>(
188  "pixelPecLayer",
189  Acts::Transform3::Identity() *
190  Acts::Translation3(0., 0., detectorHz - pixelEcHz),
191  Acts::VolumeBounds::eCylinder, pixelPecBoundaries, innerBuilder);
192 
193  pixelPec->add(std::move(pixelPecLayer));
194 
195  // Adding pixel
196  pixel->add(std::move(pixelNec));
197  pixel->add(std::move(pixelPec));
198  pixel->add(std::move(pixelBarrel));
199 
200  detector->add(std::move(pixel));
201 
202  std::ofstream fs("detector_with_gaps.dot");
203  detector->dotStream(fs);
204  fs.close();
205 
206  // Simple test
207  BOOST_CHECK(detector->children.size() == 2u);
208  BOOST_CHECK(detector->children[0u]->name == "beam_pipe");
209  BOOST_CHECK(detector->children[1u]->name == "pixel");
210 
211  // Now fill the gaps
213 
214  // Do the tests again
215  BOOST_CHECK(detector->children.size() == 4u);
216  BOOST_CHECK(detector->children[0u]->name == "beam_pipe");
217  BOOST_CHECK(detector->children[1u]->name == "detector_gap_0");
218  BOOST_CHECK(detector->children[2u]->name == "pixel");
219  BOOST_CHECK(detector->children[3u]->name == "detector_gap_1");
220 
221  // Adjustment of gap parameters
222  BOOST_CHECK(detector->children[1u]->boundaryValues[0] == beamPipeOr);
223  BOOST_CHECK(detector->children[1u]->boundaryValues[1] == pixelIr);
224  BOOST_CHECK(detector->children[1u]->boundaryValues[2] == detectorHz);
225 
226  BOOST_CHECK(detector->children[3u]->boundaryValues[0] == pixelOr);
227  BOOST_CHECK(detector->children[3u]->boundaryValues[1] == detectorOr);
228  BOOST_CHECK(detector->children[3u]->boundaryValues[2] == detectorHz);
229 
230  // Check the pixel system: Nec / Barrel / Pec
231  BOOST_CHECK(detector->children[2u]->children.size() == 3u);
232  BOOST_CHECK(detector->children[2u]->children[0u]->children.size() == 3u);
233  BOOST_CHECK(detector->children[2u]->children[1u]->children.size() == 5u);
234  BOOST_CHECK(detector->children[2u]->children[2u]->children.size() == 3u);
235 
236  // Nec test
237  BOOST_CHECK(
238  detector->children[2u]->children[0u]->children[0]->boundaryValues[0] ==
239  pixelIr);
240  BOOST_CHECK(
241  detector->children[2u]->children[0u]->children[0]->boundaryValues[1] ==
242  pixelOr);
243 
244  BOOST_CHECK(
245  detector->children[2u]->children[0u]->children[1]->boundaryValues[0] ==
246  pixelIr);
247  BOOST_CHECK(
248  detector->children[2u]->children[0u]->children[1]->boundaryValues[1] ==
249  pixelOr);
250 
251  BOOST_CHECK(
252  detector->children[2u]->children[0u]->children[2]->boundaryValues[0] ==
253  pixelIr);
254  BOOST_CHECK(
255  detector->children[2u]->children[0u]->children[2]->boundaryValues[1] ==
256  pixelOr);
257 
258  std::ofstream fs2("detector_without_gaps.dot");
259  detector->dotStream(fs2);
260  fs2.close();
261 }
262 
263 BOOST_AUTO_TEST_CASE(BlueprintCylindricalGapException) {
264  auto innerBuilder =
265  std::make_shared<Acts::Experimental::IInternalStructureBuilder>();
266 
267  // The root node - detector
268  std::vector<Acts::ActsScalar> detectorBoundaries = {0., 50., 100.};
269  std::vector<Acts::BinningValue> detectorBinning = {Acts::binX};
270  auto detector = std::make_unique<Acts::Experimental::Blueprint::Node>(
271  "detector", Acts::Transform3::Identity(), Acts::VolumeBounds::eCuboid,
272  detectorBoundaries, detectorBinning);
273 
274  std::vector<Acts::ActsScalar> cubeOneBoundaries = {0., 20., 100.};
275  auto cubeOne = std::make_unique<Acts::Experimental::Blueprint::Node>(
276  "cubeOne", Acts::Transform3::Identity(), Acts::VolumeBounds::eCuboid,
277  cubeOneBoundaries, innerBuilder);
278  detector->add(std::move(cubeOne));
279 
280  // Throw because the detector is not cylindrical (cube not yet implemented)
281  BOOST_CHECK_THROW(
283  std::runtime_error);
284 
285  // Let's change both from a cuboid to a cylinder
287  detector->children.front()->boundsType = Acts::VolumeBounds::eCylinder;
288 
289  // Add a second volume
290  std::vector<Acts::ActsScalar> volTwoBoundaries = {0., 20., 100.};
291  auto volTwo = std::make_unique<Acts::Experimental::Blueprint::Node>(
292  "volTwo", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
293  volTwoBoundaries, innerBuilder);
294  detector->add(std::move(volTwo));
295 
296  // Throw because cylinders can not be binned in x
297  BOOST_CHECK_THROW(
299  std::runtime_error);
300 }
301 
302 BOOST_AUTO_TEST_SUITE_END()