Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BuildTelescopeDetector.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file BuildTelescopeDetector.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020-2021 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 
10 
31 
32 #include <algorithm>
33 #include <cstddef>
34 #include <utility>
35 
36 std::unique_ptr<const Acts::TrackingGeometry>
39  ContextType& gctx,
40  std::vector<
41  std::shared_ptr<ActsExamples::Telescope::TelescopeDetectorElement>>&
42  detectorStore,
43  const std::vector<double>& positions,
44  const std::vector<double>& stereoAngles,
45  const std::array<double, 2>& offsets, const std::array<double, 2>& bounds,
48  using namespace Acts::UnitLiterals;
49 
50  // The rectangle bounds for plane surface
51  const auto pBounds =
52  std::make_shared<const Acts::RectangleBounds>(bounds[0], bounds[1]);
53  // The radial bounds for disc surface
54  const auto rBounds =
55  std::make_shared<const Acts::RadialBounds>(bounds[0], bounds[1]);
56 
57  // Material of the surfaces
59  9.370_cm, 46.52_cm, 28.0855, 14, 2.329_g / 1_cm3);
60  Acts::MaterialSlab matProp(silicon, thickness);
61  const auto surfaceMaterial =
62  std::make_shared<Acts::HomogeneousSurfaceMaterial>(matProp);
63 
64  // Construct the rotation
65  // This assumes the binValue is binX, binY or binZ. No reset is necessary in
66  // case of binZ
67  Acts::RotationMatrix3 rotation = Acts::RotationMatrix3::Identity();
68  if (binValue == Acts::BinningValue::binX) {
69  rotation.col(0) = Acts::Vector3(0, 0, -1);
70  rotation.col(1) = Acts::Vector3(0, 1, 0);
71  rotation.col(2) = Acts::Vector3(1, 0, 0);
72  } else if (binValue == Acts::BinningValue::binY) {
73  rotation.col(0) = Acts::Vector3(1, 0, 0);
74  rotation.col(1) = Acts::Vector3(0, 0, -1);
75  rotation.col(2) = Acts::Vector3(0, 1, 0);
76  }
77 
78  // Construct the surfaces and layers
79  size_t nLayers = positions.size();
80  std::vector<Acts::LayerPtr> layers(nLayers);
81  for (unsigned int i = 0; i < nLayers; ++i) {
82  // The translation without rotation yet
83  Acts::Translation3 trans(offsets[0], offsets[1], positions[i]);
84  // The entire transformation (the coordinate system, whose center is defined
85  // by trans, will be rotated as well)
86  Acts::Transform3 trafo(rotation * trans);
87 
88  // rotate around local z axis by stereo angle
89  auto stereo = stereoAngles[i];
90  trafo *= Acts::AngleAxis3(stereo, Acts::Vector3::UnitZ());
91 
92  // Create the detector element
93  std::shared_ptr<TelescopeDetectorElement> detElement = nullptr;
94  if (surfaceType == TelescopeSurfaceType::Plane) {
95  detElement = std::make_shared<TelescopeDetectorElement>(
96  std::make_shared<const Acts::Transform3>(trafo), pBounds, 1._um,
97  surfaceMaterial);
98  } else {
99  detElement = std::make_shared<TelescopeDetectorElement>(
100  std::make_shared<const Acts::Transform3>(trafo), rBounds, 1._um,
101  surfaceMaterial);
102  }
103  // Get the surface
104  auto surface = detElement->surface().getSharedPtr();
105  // Add the detector element to the detector store
106  detectorStore.push_back(std::move(detElement));
107  // Construct the surface array (one surface contained)
108  std::unique_ptr<Acts::SurfaceArray> surArray(
110  // Construct the layer
111  if (surfaceType == TelescopeSurfaceType::Plane) {
112  layers[i] =
113  Acts::PlaneLayer::create(trafo, pBounds, std::move(surArray), 1._mm);
114  } else {
115  layers[i] =
116  Acts::DiscLayer::create(trafo, rBounds, std::move(surArray), 1._mm);
117  }
118  // Associate the layer to the surface
119  auto mutableSurface = const_cast<Acts::Surface*>(surface.get());
120  mutableSurface->associateLayer(*layers[i]);
121  }
122 
123  // The volume transform
124  Acts::Translation3 transVol(offsets[0], offsets[1],
125  (positions.front() + positions.back()) * 0.5);
126  Acts::Transform3 trafoVol(rotation * transVol);
127 
128  // The volume bounds is set to be a bit larger than either cubic with planes
129  // or cylinder with discs
130  auto length = positions.back() - positions.front();
131  Acts::VolumeBoundsPtr boundsVol = nullptr;
132  if (surfaceType == TelescopeSurfaceType::Plane) {
133  boundsVol = std::make_shared<const Acts::CuboidVolumeBounds>(
134  bounds[0] + 5._mm, bounds[1] + 5._mm, length + 10._mm);
135  } else {
136  boundsVol = std::make_shared<const Acts::CylinderVolumeBounds>(
137  std::max(bounds[0] - 5.0_mm, 0.), bounds[1] + 5._mm, length + 10._mm);
138  }
139 
141  Acts::LayerArrayCreator layArrCreator(
142  lacConfig,
143  Acts::getDefaultLogger("LayerArrayCreator", Acts::Logging::INFO));
144  Acts::LayerVector layVec;
145  for (unsigned int i = 0; i < nLayers; i++) {
146  layVec.push_back(layers[i]);
147  }
148  // Create the layer array
149  Acts::GeometryContext genGctx{gctx};
150  std::unique_ptr<const Acts::LayerArray> layArr(layArrCreator.layerArray(
151  genGctx, layVec, positions.front() - 2._mm, positions.back() + 2._mm,
153 
154  // Build the tracking volume
155  auto trackVolume =
156  Acts::TrackingVolume::create(trafoVol, boundsVol, nullptr,
157  std::move(layArr), nullptr, {}, "Telescope");
158 
159  // Build and return tracking geometry
160  return std::make_unique<Acts::TrackingGeometry>(trackVolume);
161 }