Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
VolumeStructureBuilder.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file VolumeStructureBuilder.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 
10 
21 
24  std::unique_ptr<const Acts::Logger> mlogger)
25  : IExternalStructureBuilder(), m_cfg(cfg), m_logger(std::move(mlogger)) {
26  // Sanity cross-checks
27  if (m_cfg.boundValues.empty() and not m_cfg.extent.has_value()) {
28  throw std::invalid_argument(
29  "VolumeStructureBuilder: no extent nor boundary values given");
30  }
31  // Check for the bounds type
32  if (m_cfg.boundsType == VolumeBounds::BoundsType::eOther) {
33  throw std::invalid_argument(
34  "VolumeStructureBuilder: no known volume bounds type provided.");
35  }
36 }
37 
40  [[maybe_unused]] const Acts::GeometryContext& gctx) const {
41  // Print out the auxiliary information
42  if (not m_cfg.auxiliary.empty()) {
43  ACTS_DEBUG(m_cfg.auxiliary);
44  }
45 
46  // The volume bounds to be constructed
47  std::unique_ptr<VolumeBounds> volumeBounds = nullptr;
48 
49  // The transform from the extent
50  auto eTransform = Transform3::Identity();
51  std::vector<ActsScalar> boundValues = m_cfg.boundValues;
52 
53  // This code dispatches into the dedicated volume types
54  switch (m_cfg.boundsType) {
55  case VolumeBounds::BoundsType::eCone: {
56  ACTS_VERBOSE("Building conical volume bounds.");
57  // Cone translation - only pre-defined values
58  if (boundValues.size() < 5u) {
59  throw std::runtime_error(
60  "VolumeStructureBuilder: parameters for cone volume bounds need to "
61  "be fully provided, they can not be estimated from an Extent "
62  "object. It needs at least 5 parameters, while " +
63  std::to_string(boundValues.size()) + " where given");
64  }
65  auto bArray = to_array<ConeVolumeBounds::BoundValues::eSize, ActsScalar>(
66  boundValues);
67  volumeBounds = std::make_unique<ConeVolumeBounds>(bArray);
68  } break;
69  case VolumeBounds::BoundsType::eCuboid: {
70  ACTS_VERBOSE("Building cuboid volume bounds.");
71  // Cuboid translation - either parameters / or extent
72  if (boundValues.empty() and m_cfg.extent.has_value()) {
73  ACTS_VERBOSE("Cuboid: estimate parameters from Extent.");
74  const auto& vExtent = m_cfg.extent.value();
75  if (vExtent.constrains(binX) and vExtent.constrains(binY) and
76  vExtent.constrains(binZ)) {
77  eTransform.pretranslate(Vector3(vExtent.medium(binX),
78  vExtent.medium(binY),
79  vExtent.medium(binZ)));
80  boundValues = {0.5 * vExtent.interval(binX),
81  0.5 * vExtent.interval(binY),
82  0.5 * vExtent.interval(binZ)};
83 
84  } else {
85  throw std::runtime_error(
86  "VolumeStructureBuilder: translation to cuboid does not work as "
87  "the extent does not constrain all necessary value.");
88  }
89  } else if (boundValues.size() < 3u) {
90  throw std::runtime_error(
91  "VolumeStructureBuilder: parameters for cuboid volume bounds need "
92  "to be fully provided, it needs exactly 3 parameters, while " +
93  std::to_string(boundValues.size()) + " where given");
94  }
95  auto bArray =
96  to_array<CuboidVolumeBounds::BoundValues::eSize>(boundValues);
97  volumeBounds = std::make_unique<CuboidVolumeBounds>(bArray);
98  } break;
99  case VolumeBounds::BoundsType::eCutoutCylinder: {
100  ACTS_VERBOSE("Building cutout cylindrical volume bounds.");
101  // Cutout cylinder translation - only parameters
102  if (boundValues.size() < 5u) {
103  throw std::runtime_error(
104  "VolumeStructureBuilder: parameters for cutout cylinder volume "
105  "bounds need to be fully provided, they can not be estimated from "
106  "an Extent object. It needs exactly 3 parameters, while " +
107  std::to_string(boundValues.size()) + " where given");
108  }
109  auto bArray =
110  to_array<CutoutCylinderVolumeBounds::BoundValues::eSize>(boundValues);
111  volumeBounds = std::make_unique<CutoutCylinderVolumeBounds>(bArray);
112  } break;
113  case VolumeBounds::BoundsType::eCylinder: {
114  ACTS_VERBOSE("Building cylindrical volume bounds.");
115  // Cylinder translation - either parameters / or extent
116  if (boundValues.empty() and m_cfg.extent.has_value()) {
117  ACTS_VERBOSE("Cylinder: estimate parameters from Extent.");
118  const auto& vExtent = m_cfg.extent.value();
119  if (vExtent.constrains(binR) and vExtent.constrains(binZ)) {
120  eTransform.pretranslate(Vector3(0., 0., vExtent.medium(binZ)));
121  boundValues = {vExtent.min(binR), vExtent.max(binR),
122  0.5 * vExtent.interval(binZ)};
123  if (vExtent.constrains(binPhi)) {
124  boundValues.push_back(0.5 * vExtent.interval(binPhi));
125  boundValues.push_back(vExtent.medium(binPhi));
126  }
127  } else {
128  throw std::runtime_error(
129  "VolumeStructureBuilder: translation to cuboid does not work as "
130  "the extent does not constrain all necessary values.");
131  }
132  } else if (boundValues.size() < 3u) {
133  throw std::runtime_error(
134  "VolumeStructureBuilder: parameters for cylinder volume "
135  "bounds need to be fully provided, it needs at least 3 parameters, "
136  "while " +
137  std::to_string(boundValues.size()) + " where given");
138  }
139  // Check if phi has been constraint, otherwise fill it with full coverage
140  if (boundValues.size() == 3u) {
141  boundValues.push_back(M_PI);
142  boundValues.push_back(0.);
143  }
144  ACTS_VERBOSE(" - cylindrical shape with [iR, oR, hZ, sPhi, mPhi] = "
145  << boundValues[0] << ", " << boundValues[1] << ", "
146  << boundValues[2] << ", " << boundValues[3] << ", "
147  << boundValues[4]);
148  auto bArray =
149  to_array<CylinderVolumeBounds::BoundValues::eSize>(boundValues);
150  volumeBounds = std::make_unique<CylinderVolumeBounds>(bArray);
151  } break;
152  case VolumeBounds::BoundsType::eGenericCuboid: {
153  ACTS_VERBOSE("Building generic cuboid volume bounds.");
154  // Generic cuboid translation - parameters only
155  if (boundValues.size() < GenericCuboidVolumeBounds::BoundValues::eSize) {
156  throw std::runtime_error(
157  "VolumeStructureBuilder: parameters for generic cuboid volume "
158  "bounds need to be provided, they can not be estimated from an "
159  "Extent object. It needs exactly 24 parameters, while " +
160  std::to_string(boundValues.size()) + " where given");
161  }
162  auto bArray =
163  to_array<GenericCuboidVolumeBounds::BoundValues::eSize>(boundValues);
164  volumeBounds = std::make_unique<GenericCuboidVolumeBounds>(bArray);
165  } break;
166  case VolumeBounds::BoundsType::eTrapezoid: {
167  ACTS_VERBOSE("Building trapezoid volume bounds.");
168  // Trapezoid translation - parameters only
169  if (boundValues.size() < 4u) {
170  throw std::runtime_error(
171  "VolumeStructureBuilder: parameters for trapezoid volume bounds "
172  "need to be provided, they can not be estimated from an Extent "
173  "object. It needs at least 4 parameters, while " +
174  std::to_string(boundValues.size()) + " where given");
175  }
176  auto bArray =
177  to_array<TrapezoidVolumeBounds::BoundValues::eSize>(boundValues);
178  volumeBounds = std::make_unique<TrapezoidVolumeBounds>(bArray);
179  } break;
180  default:
181  break;
182  }
183 
184  Transform3 fTransform = m_cfg.transform * eTransform;
185  ACTS_VERBOSE(" - translation: " << Acts::toString(fTransform.translation()));
186  if (not fTransform.rotation().isApprox(
187  Acts::Transform3::Identity().rotation())) {
188  ACTS_VERBOSE(" - rotation: " << Acts::toString(fTransform.rotation()));
189  }
190  // Return the transform, the volume bounds, and some default portal
191  // generators
192  return {fTransform, std::move(volumeBounds), defaultPortalGenerator()};
193 }