Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BlueprintHelper.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file BlueprintHelper.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 
14 
15 #include <array>
16 
17 namespace {
18 
19 std::array<Acts::Vector3, 2u> cylEndpointsZ(
21  Acts::Vector3 axisZ = node.transform.rotation().col(2);
22  auto halfZ = node.boundaryValues[2];
23  Acts::Vector3 center = node.transform.translation();
24  Acts::Vector3 p0 = center - halfZ * axisZ;
25  Acts::Vector3 p1 = center + halfZ * axisZ;
26  return {p0, p1};
27 }
28 
29 } // namespace
30 
32  bool recursive) {
33  if (node.children.size() < 2u) {
34  return;
35  }
36  // Sort along x, y, z
37  if (node.binning.size() == 1) {
38  auto bVal = node.binning.front();
39  // x,y,z binning along the axis
40  if (bVal == binX or bVal == binY or bVal == binZ) {
41  Vector3 nodeCenter = node.transform.translation();
42  Vector3 nodeSortAxis = node.transform.rotation().col(bVal);
43  std::sort(
44  node.children.begin(), node.children.end(),
45  [&](const auto& a, const auto& b) {
46  return (a->transform.translation() - nodeCenter).dot(nodeSortAxis) <
47  (b->transform.translation() - nodeCenter).dot(nodeSortAxis);
48  });
49  } else if (bVal == binR and node.boundsType == VolumeBounds::eCylinder) {
50  std::sort(node.children.begin(), node.children.end(),
51  [](const auto& a, const auto& b) {
52  return 0.5 * (a->boundaryValues[0] + a->boundaryValues[1]) <
53  0.5 * (b->boundaryValues[0] + b->boundaryValues[1]);
54  });
55  }
56  }
57 
58  // Sort the children
59  if (recursive) {
60  for (auto& child : node.children) {
61  sort(*child, true);
62  }
63  }
64 }
65 
67  Blueprint::Node& node, bool adjustToParent) {
68  // Return if this is a leaf node
69  if (node.isLeaf()) {
70  return;
71  }
72 
73  if (node.boundsType == VolumeBounds::eCylinder) {
74  // Nodes must be sorted
75  sort(node, false);
76 
77  // Container values
78  auto cInnerR = node.boundaryValues[0];
79  auto cOuterR = node.boundaryValues[1];
80  auto cHalfZ = node.boundaryValues[2];
81 
82  std::vector<std::unique_ptr<Blueprint::Node>> gaps;
83  // Only 1D binning implemented for the moment
84  if (node.binning.size() == 1) {
85  auto bVal = node.binning.front();
86  if (bVal == binZ) {
87  // adjust inner/outer radius
88  if (adjustToParent) {
89  std::for_each(node.children.begin(), node.children.end(),
90  [&](auto& child) {
91  child->boundaryValues[0] = cInnerR;
92  child->boundaryValues[1] = cOuterR;
93  });
94  }
95  auto [negC, posC] = cylEndpointsZ(node);
96  // Assume sorted along the local z axis
97  unsigned int igap = 0;
98  for (auto& child : node.children) {
99  auto [neg, pos] = cylEndpointsZ(*child);
100  ActsScalar gapSpan = (neg - negC).norm();
101  if (gapSpan > s_onSurfaceTolerance) {
102  // Fill a gap node
103  auto gapName = node.name + "_gap_" + std::to_string(igap);
104  auto gapTransform = Transform3::Identity();
105  gapTransform.rotate(node.transform.rotation());
106  gapTransform.translate(0.5 * (neg + negC));
107  auto gap = std::make_unique<Blueprint::Node>(
108  gapName, gapTransform, VolumeBounds::eCylinder,
109  std::vector<ActsScalar>{cInnerR, cOuterR, 0.5 * gapSpan});
110  gaps.push_back(std::move(gap));
111  ++igap;
112  }
113  // Set to new current negative value
114  negC = pos;
115  }
116  // Check if a last one needs to be filled
117  ActsScalar gapSpan = (negC - posC).norm();
118  if (gapSpan > s_onSurfaceTolerance) {
119  // Fill a gap node
120  auto gapName = node.name + "_gap_" + std::to_string(igap);
121  auto gapTransform = Transform3::Identity();
122  gapTransform.rotate(node.transform.rotation());
123  gapTransform.translate(0.5 * (negC + posC));
124  auto gap = std::make_unique<Blueprint::Node>(
125  gapName, gapTransform, VolumeBounds::eCylinder,
126  std::vector<ActsScalar>{cInnerR, cOuterR, 0.5 * gapSpan});
127  gaps.push_back(std::move(gap));
128  }
129 
130  } else if (bVal == binR) {
131  // We have binning in R present
132  if (adjustToParent) {
133  std::for_each(node.children.begin(), node.children.end(),
134  [&](auto& child) {
135  child->transform = node.transform;
136  child->boundaryValues[2] = cHalfZ;
137  });
138  }
139  // Fill the gaps in R
140  unsigned int igap = 0;
141  ActsScalar lastR = cInnerR;
142  for (auto& child : node.children) {
143  ActsScalar iR = child->boundaryValues[0];
144  if (std::abs(iR - lastR) > s_onSurfaceTolerance) {
145  auto gap = std::make_unique<Blueprint::Node>(
146  node.name + "_gap_" + std::to_string(igap), node.transform,
147  VolumeBounds::eCylinder,
148  std::vector<ActsScalar>{lastR, iR, cHalfZ});
149  gaps.push_back(std::move(gap));
150  ++igap;
151  }
152  // Set to new outer radius
153  lastR = child->boundaryValues[1];
154  }
155  // Check if a last one needs to be filled
156  if (std::abs(lastR - cOuterR) > s_onSurfaceTolerance) {
157  auto gap = std::make_unique<Blueprint::Node>(
158  node.name + "_gap_" + std::to_string(igap), node.transform,
159  VolumeBounds::eCylinder,
160  std::vector<ActsScalar>{lastR, cOuterR, cHalfZ});
161  gaps.push_back(std::move(gap));
162  }
163  } else {
164  throw std::runtime_error(
165  "BlueprintHelper: gap filling not implemented for "
166  "cylinder and this binning type.");
167  }
168  }
169  // Insert
170  for (auto& gap : gaps) {
171  node.add(std::move(gap));
172  }
173 
174  // Sort again after inserting
175  sort(node, false);
176  // Fill the gaps recursively
177  for (auto& child : node.children) {
178  fillGaps(*child, adjustToParent);
179  }
180 
181  } else {
182  throw std::runtime_error(
183  "BlueprintHelper: gap filling not implemented for "
184  "this boundary type");
185  }
186 }