Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CylindricalDetectorFromBlueprintTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CylindricalDetectorFromBlueprintTests.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 
26 
27 #include <fstream>
28 
29 template <typename surface_type>
31  public:
34  : m_surface(Acts::Surface::makeShared<surface_type>(trf, p0, p1)) {}
41  [[maybe_unused]] const Acts::GeometryContext& gctx) const final {
42  // Trivialities first: internal volumes
43  std::vector<std::shared_ptr<Acts::Experimental::DetectorVolume>>
44  internalVolumes = {};
45  Acts::Experimental::DetectorVolumeUpdator internalVolumeUpdator =
47 
48  // Retrieve the layer surfaces
49  Acts::Experimental::SurfaceCandidatesUpdator internalCandidatesUpdator =
51 
52  // Return the internal structure
54  {m_surface},
55  internalVolumes,
56  std::move(internalCandidatesUpdator),
57  std::move(internalVolumeUpdator)};
58  }
59 
60  private:
61  std::shared_ptr<Acts::Surface> m_surface;
62 };
63 
64 BOOST_AUTO_TEST_SUITE(Detector)
65 
66 BOOST_AUTO_TEST_CASE(CylindricalDetectorFromBlueprintTest) {
68 
69  // This tests shows how to careate cylindrical detector from a detector
70  // blueprint.
71  //
72  // In general, the blueprint (lines below) is generated through reading in
73  // or by parsing the geometry model (DD4heo, TGeo, Geant4, etc.). For
74  // testing purpose, let us create the blueprint manually.
75  //
76 
77  // Blueprint starts here ----------------
78 
79  // Detector dimensions
80  Acts::ActsScalar detectorIr = 0.;
81  Acts::ActsScalar detectorOr = 120.;
82  Acts::ActsScalar detectorHz = 400.;
83 
84  // Beam pipe
85  Acts::ActsScalar beamPipeOr = 20.;
86 
87  // Pixel system
88  Acts::ActsScalar pixelIr = 25;
89  Acts::ActsScalar pixelOr = 115;
90  Acts::ActsScalar pixelEcHz = 50;
91  Acts::ActsScalar pixelEcLayerHz = 10;
92 
93  // Create root node
94  std::vector<Acts::BinningValue> detectorBinning = {Acts::binR};
95  std::vector<Acts::ActsScalar> detectorBoundaries = {detectorIr, detectorOr,
96  detectorHz};
97 
98  // The root node - detector
99  auto detectorBpr = std::make_unique<Acts::Experimental::Blueprint::Node>(
100  "detector", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
101  detectorBoundaries, detectorBinning);
102 
103  // The beam pipe
104  std::vector<Acts::ActsScalar> beamPipeBoundaries = {detectorIr, beamPipeOr,
105  detectorHz};
106 
107  auto beamPipeStructure =
108  std::make_shared<SurfaceBuilder<Acts::CylinderSurface>>(
109  Acts::Transform3::Identity(), 18, 0.99 * detectorHz);
110  auto beamPipe = std::make_unique<Acts::Experimental::Blueprint::Node>(
111  "beam_pipe", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
112  beamPipeBoundaries, beamPipeStructure);
113  detectorBpr->add(std::move(beamPipe));
114 
115  // A pixel system
116  std::vector<Acts::ActsScalar> pixelBoundaries = {pixelIr, pixelOr,
117  detectorHz};
118  std::vector<Acts::BinningValue> pixelBinning = {Acts::binZ};
119  auto pixel = std::make_unique<Acts::Experimental::Blueprint::Node>(
120  "pixel", Acts::Transform3::Identity(), Acts::VolumeBounds::eCylinder,
121  pixelBoundaries, pixelBinning);
122 
123  // Nec: Small differences to check if the adjustments are made
124  std::vector<Acts::ActsScalar> pixelEcBoundaries = {pixelIr, pixelOr - 5.,
125  pixelEcHz};
126  std::vector<Acts::BinningValue> pixelEcBinning = {Acts::binZ};
127 
128  Acts::Transform3 pixelNecTransform =
129  Acts::Transform3::Identity() *
130  Acts::Translation3(0., 0., -detectorHz + pixelEcHz);
131 
132  auto pixelNec = std::make_unique<Acts::Experimental::Blueprint::Node>(
133  "pixel_nec", pixelNecTransform, Acts::VolumeBounds::eCylinder,
134  pixelEcBoundaries, pixelEcBinning);
135 
136  // Add a single encap layer
137  std::vector<Acts::ActsScalar> pixelNecBoundaries = {pixelIr + 2, pixelOr - 7.,
138  pixelEcLayerHz};
139 
140  auto pixelNecLayerStructure =
141  std::make_shared<SurfaceBuilder<Acts::DiscSurface>>(
142  pixelNecTransform, pixelIr + 10., pixelOr - 10.);
143 
144  auto pixelNecLayer = std::make_unique<Acts::Experimental::Blueprint::Node>(
145  "pixel_nec_layer", pixelNecTransform, Acts::VolumeBounds::eCylinder,
146  pixelNecBoundaries, pixelNecLayerStructure);
147 
148  pixelNec->add(std::move(pixelNecLayer));
149 
150  // Barrel
151  std::vector<Acts::ActsScalar> pixelBarrelBoundaries = {
152  pixelIr + 1, pixelOr - 1., detectorHz - 2 * pixelEcHz};
153  std::vector<Acts::BinningValue> pixelBarrelBinning = {Acts::binR};
154 
155  auto pixelBarrel = std::make_unique<Acts::Experimental::Blueprint::Node>(
156  "pixel_barrel", Acts::Transform3::Identity(),
157  Acts::VolumeBounds::eCylinder, pixelBarrelBoundaries, pixelBarrelBinning);
158 
159  auto pixelBarrelL0Structure =
160  std::make_shared<SurfaceBuilder<Acts::CylinderSurface>>(
161  Acts::Transform3::Identity(), 62.5, detectorHz - 2 * pixelEcHz - 10.);
162  std::vector<Acts::ActsScalar> pixelBarrelL0Boundaries = {
163  60, 65., detectorHz - 2 * pixelEcHz};
164  auto pixelBarrelL0 = std::make_unique<Acts::Experimental::Blueprint::Node>(
165  "pixel_barrel_l0", Acts::Transform3::Identity(),
166  Acts::VolumeBounds::eCylinder, pixelBarrelL0Boundaries,
167  pixelBarrelL0Structure);
168 
169  auto pixelBarrelL1Structure =
170  std::make_shared<SurfaceBuilder<Acts::CylinderSurface>>(
171  Acts::Transform3::Identity(), 102.5,
172  detectorHz - 2 * pixelEcHz - 10.);
173 
174  std::vector<Acts::ActsScalar> pixelBarrelL1Boundaries = {
175  100, 105., detectorHz - 2 * pixelEcHz};
176  auto pixelBarrelL1 = std::make_unique<Acts::Experimental::Blueprint::Node>(
177  "pixel_barrel_l1", Acts::Transform3::Identity(),
178  Acts::VolumeBounds::eCylinder, pixelBarrelL1Boundaries,
179  pixelBarrelL1Structure);
180  pixelBarrel->add(std::move(pixelBarrelL0));
181  pixelBarrel->add(std::move(pixelBarrelL1));
182 
183  Acts::Transform3 pixelPecTransform =
184  Acts::Transform3::Identity() *
185  Acts::Translation3(0., 0., detectorHz - pixelEcHz);
186 
187  auto pixelPec = std::make_unique<Acts::Experimental::Blueprint::Node>(
188  "pixel_pec", pixelPecTransform, Acts::VolumeBounds::eCylinder,
189  pixelEcBoundaries, pixelEcBinning);
190 
191  std::vector<Acts::ActsScalar> pixelPecBoundaries = {pixelIr + 2, pixelOr - 7.,
192  10.};
193 
194  auto pixelPecLayerStructure =
195  std::make_shared<SurfaceBuilder<Acts::DiscSurface>>(
196  pixelPecTransform, pixelIr + 10., pixelOr - 10.);
197 
198  auto pixelPecLayer = std::make_unique<Acts::Experimental::Blueprint::Node>(
199  "pixel_pec_layer", pixelPecTransform, Acts::VolumeBounds::eCylinder,
200  pixelPecBoundaries, pixelPecLayerStructure);
201 
202  pixelPec->add(std::move(pixelPecLayer));
203 
204  // Adding pixel
205  pixel->add(std::move(pixelNec));
206  pixel->add(std::move(pixelPec));
207  pixel->add(std::move(pixelBarrel));
208 
209  detectorBpr->add(std::move(pixel));
210 
211  // An Indexed volume finder will be attached
212  std::vector<Acts::BinningValue> rootVolumeBinning = {Acts::binZ, Acts::binR};
213  detectorBpr->rootVolumeFinderBuilder =
214  std::make_shared<Acts::Experimental::IndexedRootVolumeFinderBuilder>(
215  rootVolumeBinning);
216 
217  // A geo ID generator
218  detectorBpr->geoIdGenerator =
219  std::make_shared<Acts::Experimental::GeometryIdGenerator>(
221  Acts::getDefaultLogger("RecursiveIdGenerator",
223 
224  // Complete and fill gaps
226 
227  std::fstream fs("cylindrical_detector_blueprint.dot", std::ios::out);
228  detectorBpr->dotStream(fs, "blueprint2cylinder");
229  fs.close();
230 
231  // ----------------------------- end of blueprint
232 
233  // Create a Cylindrical detector builder from this blueprint
234  auto detectorBuilder =
235  std::make_shared<Acts::Experimental::CylindricalContainerBuilder>(
236  *detectorBpr, Acts::Logging::VERBOSE);
237 
238  // Detector builder
240  dCfg.auxiliary =
241  "*** Test : auto generated cylindrical detector builder ***";
242  dCfg.name = "Cylindrical detector from blueprint";
243  dCfg.builder = detectorBuilder;
244  dCfg.geoIdGenerator = detectorBpr->geoIdGenerator;
245 
247 
248  BOOST_CHECK(detector != nullptr);
249 
250  // There should be 14 volumes, and they should be built in order
251  // beam_pipe
252  // detector_gap_0
253  // pixel_nec_gap_0
254  // pixel_nec_layer
255  // pixel_nec_gap_1
256  // pixel_barrel_gap_0
257  // pixel_barrel_l0
258  // pixel_barrel_gap_1
259  // pixel_barrel_l1
260  // pixel_barrel_gap_2
261  // pixel_pec_gap_0
262  // pixel_pec_layer
263  // pixel_pec_gap_1
264  // detector_gap_1
265  BOOST_CHECK(detector->volumes().size() == 14u);
266  BOOST_CHECK(detector->volumes()[0]->name() == "beam_pipe");
267  BOOST_CHECK(detector->volumes()[1]->name() == "detector_gap_0");
268  BOOST_CHECK(detector->volumes()[2]->name() == "pixel_nec_gap_0");
269  BOOST_CHECK(detector->volumes()[3]->name() == "pixel_nec_layer");
270  BOOST_CHECK(detector->volumes()[4]->name() == "pixel_nec_gap_1");
271  BOOST_CHECK(detector->volumes()[5]->name() == "pixel_barrel_gap_0");
272  BOOST_CHECK(detector->volumes()[6]->name() == "pixel_barrel_l0");
273  BOOST_CHECK(detector->volumes()[7]->name() == "pixel_barrel_gap_1");
274  BOOST_CHECK(detector->volumes()[8]->name() == "pixel_barrel_l1");
275  BOOST_CHECK(detector->volumes()[9]->name() == "pixel_barrel_gap_2");
276  BOOST_CHECK(detector->volumes()[10]->name() == "pixel_pec_gap_0");
277  BOOST_CHECK(detector->volumes()[11]->name() == "pixel_pec_layer");
278  BOOST_CHECK(detector->volumes()[12]->name() == "pixel_pec_gap_1");
279  BOOST_CHECK(detector->volumes()[13]->name() == "detector_gap_1");
280 }
281 
282 BOOST_AUTO_TEST_SUITE_END()