Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TGeoITkModuleSplitter.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TGeoITkModuleSplitter.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2016-2020 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 
17 
18 #include <algorithm>
19 #include <array>
20 #include <cstddef>
21 #include <sstream>
22 
25  std::unique_ptr<const Acts::Logger> logger)
26  : m_cfg(cfg), m_logger(std::move(logger)) {
28 }
29 
31  m_splitCategories.reserve(m_cfg.splitPatterns.size());
32  for (const std::pair<const std::string, std::string>& pattern_split_category :
33  m_cfg.splitPatterns) {
34  // mark pattern for disc or barrel module splits:
35  bool is_disk = false;
36  if (m_cfg.discMap.find(pattern_split_category.second) !=
37  m_cfg.discMap.end()) {
38  is_disk = true;
39  } else if (m_cfg.barrelMap.find(pattern_split_category.second) ==
40  m_cfg.barrelMap.end()) {
41  ACTS_ERROR(
42  pattern_split_category.second +
43  " is neither a category name for barrel or disk module splits.");
44  continue;
45  }
46  m_splitCategories.push_back(
47  std::make_tuple(std::regex(pattern_split_category.first),
48  pattern_split_category.second, is_disk));
49  }
50 }
51 
53 inline std::vector<std::shared_ptr<const Acts::TGeoDetectorElement>>
56  std::shared_ptr<const Acts::TGeoDetectorElement> detElement) const {
57  // Is the current node covered by this splitter?
58  const TGeoNode& node = detElement->tgeoNode();
59  auto sensorName = std::string(node.GetName());
60 
61  static const char* category_names[2] = {"barrel", "disc"};
62  for (const std::tuple<std::regex, std::string, bool>& split_category :
63  m_splitCategories) {
64  if (std::regex_match(sensorName, std::get<0>(split_category))) {
65  ACTS_DEBUG("Splitting " +
66  std::string(category_names[std::get<2>(split_category)]) +
67  " node " + sensorName + " using split ranges of category " +
68  std::get<1>(split_category));
69  if (!std::get<2>(split_category)) {
71  gctx, detElement, m_cfg.barrelMap.at(std::get<1>(split_category)));
72  } else {
74  gctx, detElement, m_cfg.discMap.at(std::get<1>(split_category)));
75  }
76  }
77  }
78  ACTS_DEBUG("No matching configuration found. Node " +
79  std::string(detElement->tgeoNode().GetName()) +
80  " will not be split.");
81 
82  return {detElement};
83 }
84 
86 inline std::vector<std::shared_ptr<const Acts::TGeoDetectorElement>>
89  const std::shared_ptr<const Acts::TGeoDetectorElement>& detElement,
90  unsigned int nSegments) const {
91  // Retrieve the surface
92  auto identifier = detElement->identifier();
93  const Acts::Surface& surface = detElement->surface();
94  const Acts::SurfaceBounds& bounds = surface.bounds();
95  if (bounds.type() != Acts::SurfaceBounds::eRectangle or nSegments <= 1u) {
96  ACTS_WARNING("Invalid splitting config for barrel node: " +
97  std::string(detElement->tgeoNode().GetName()) +
98  "! Node will not be slpit.");
99  return {detElement};
100  }
101 
102  // Output container for the submodules
103  std::vector<std::shared_ptr<const Acts::TGeoDetectorElement>> detElements =
104  {};
105  detElements.reserve(nSegments);
106 
107  // Get the geometric information
108  double thickness = detElement->thickness();
109  const Acts::Transform3& transform = surface.transform(gctx);
110  // Determine the new bounds
111  const std::vector<double> boundsValues = bounds.values();
112  double lengthX = (boundsValues[Acts::RectangleBounds::eMaxX] -
113  boundsValues[Acts::RectangleBounds::eMinX]) /
114  nSegments;
115  double lengthY = boundsValues[Acts::RectangleBounds::eMaxY] -
116  boundsValues[Acts::RectangleBounds::eMinY];
117  auto rectBounds =
118  std::make_shared<Acts::RectangleBounds>(0.5 * lengthX, 0.5 * lengthY);
119  // Translation for every subelement
120  auto localTranslation = Acts::Vector2(-0.5 * lengthX * (nSegments - 1), 0.);
121  const auto step = Acts::Vector2(lengthX, 0.);
122  ACTS_DEBUG("Rectangle bounds for new node (half length): " +
123  std::to_string(rectBounds->halfLengthX()) + ", " +
124  std::to_string(rectBounds->halfLengthY()));
125 
126  for (size_t i = 0; i < nSegments; i++) {
127  Acts::Vector3 globalTranslation =
128  surface.localToGlobal(gctx, localTranslation, {}) -
129  transform.translation();
130  auto elemTransform =
131  Acts::Transform3(transform).pretranslate(globalTranslation);
132  auto element = std::make_shared<const Acts::TGeoDetectorElement>(
133  identifier, detElement->tgeoNode(), elemTransform, rectBounds,
134  thickness);
135  detElements.push_back(std::move(element));
136 
137  localTranslation += step;
138  }
139  return detElements;
140 }
141 
143 inline std::vector<std::shared_ptr<const Acts::TGeoDetectorElement>>
146  const std::shared_ptr<const Acts::TGeoDetectorElement>& detElement,
147  const std::vector<ActsExamples::TGeoITkModuleSplitter::SplitRange>&
148  splitRanges) const {
149  // Retrieve the surface
150  auto identifier = detElement->identifier();
151  const Acts::Surface& surface = detElement->surface();
152  const Acts::SurfaceBounds& bounds = surface.bounds();
153 
154  // Check annulus bounds origin
155  auto printOrigin = [&](const Acts::Surface& sf) {
156  Acts::Vector3 discOrigin =
157  sf.localToGlobal(gctx, Acts::Vector2(0., 0.), Acts::Vector3::Zero());
158  std::string out =
159  "Disc surface origin at: " + std::to_string(discOrigin[0]) + ", " +
160  std::to_string(discOrigin[1]) + ", " + std::to_string(discOrigin[2]);
161  return out;
162  };
163  ACTS_DEBUG(printOrigin(surface));
164 
165  if (bounds.type() != Acts::SurfaceBounds::eAnnulus or splitRanges.empty()) {
166  ACTS_WARNING("Invalid splitting config for disk node: " +
167  std::string(detElement->tgeoNode().GetName()) +
168  "! Node will not be slpit.");
169  return {detElement};
170  }
171 
172  auto nSegments = splitRanges.size();
173 
174  // Output container for the submodules
175  std::vector<std::shared_ptr<const Acts::TGeoDetectorElement>> detElements =
176  {};
177  detElements.reserve(nSegments);
178 
179  // Get the geometric information
180  double thickness = detElement->thickness();
181  const Acts::Transform3& transform = surface.transform(gctx);
182  const std::vector<double> boundsValues = bounds.values();
183  std::array<double, Acts::AnnulusBounds::eSize> values{};
184  std::copy_n(boundsValues.begin(), Acts::AnnulusBounds::eSize, values.begin());
185 
186  for (size_t i = 0; i < nSegments; i++) {
187  values[Acts::AnnulusBounds::eMinR] = splitRanges[i].first;
188  values[Acts::AnnulusBounds::eMaxR] = splitRanges[i].second;
189  auto annulusBounds = std::make_shared<Acts::AnnulusBounds>(values);
190  ACTS_DEBUG(
191  "New r bounds for node: " + std::to_string(annulusBounds->rMin()) +
192  ", " + std::to_string(annulusBounds->rMax()));
193 
194  auto element = std::make_shared<const Acts::TGeoDetectorElement>(
195  identifier, detElement->tgeoNode(), transform, annulusBounds,
196  thickness);
197  detElements.push_back(std::move(element));
198  }
199  return detElements;
200 }