Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TGeoCylinderDiscSplitter.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TGeoCylinderDiscSplitter.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 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 
19 
20 #include <cmath>
21 #include <cstdlib>
22 #include <utility>
23 
26  std::unique_ptr<const Acts::Logger> logger)
27  : m_cfg(cfg), m_logger(std::move(logger)) {}
28 
29 std::vector<std::shared_ptr<const Acts::TGeoDetectorElement>>
31  const GeometryContext& gctx,
32  std::shared_ptr<const Acts::TGeoDetectorElement> tgde) const {
33  const Acts::Surface& sf = tgde->surface();
34  // Thickness
35  auto tgIdentifier = tgde->identifier();
36  const TGeoNode& tgNode = tgde->tgeoNode();
37  ActsScalar tgThickness = tgde->thickness();
38 
39  // Disc segments are detected, attempt a split
40  if (m_cfg.discPhiSegments > 0 or m_cfg.discRadialSegments > 0) {
41  // Splitting for discs detected
42  if (sf.type() == Acts::Surface::Disc and
44  ACTS_DEBUG("- splitting detected for a Disc shaped sensor.");
45 
46  std::vector<std::shared_ptr<const Acts::TGeoDetectorElement>>
47  tgDetectorElements = {};
48  tgDetectorElements.reserve(std::abs(m_cfg.discPhiSegments) *
49  std::abs(m_cfg.discRadialSegments));
50 
51  const Acts::Vector3 discCenter = sf.center(gctx);
52 
53  const auto& boundValues = sf.bounds().values();
54  ActsScalar discMinR = boundValues[Acts::RadialBounds::eMinR];
55  ActsScalar discMaxR = boundValues[Acts::RadialBounds::eMaxR];
56 
57  ActsScalar phiStep = 2 * M_PI / m_cfg.discPhiSegments;
58  ActsScalar cosPhiHalf = std::cos(0.5 * phiStep);
59  ActsScalar sinPhiHalf = std::sin(0.5 * phiStep);
60 
61  std::vector<ActsScalar> radialValues = {};
62  if (m_cfg.discRadialSegments > 1) {
63  ActsScalar rStep = (discMaxR - discMinR) / m_cfg.discRadialSegments;
64  radialValues.reserve(m_cfg.discRadialSegments);
65  for (int ir = 0; ir <= m_cfg.discRadialSegments; ++ir) {
66  radialValues.push_back(discMinR + ir * rStep);
67  }
68  } else {
69  radialValues = {discMinR, discMaxR};
70  }
71 
72  for (size_t ir = 1; ir < radialValues.size(); ++ir) {
73  ActsScalar minR = radialValues[ir - 1];
74  ActsScalar maxR = radialValues[ir];
75 
76  ActsScalar maxLocY = maxR * cosPhiHalf;
77  ActsScalar minLocY = minR * cosPhiHalf;
78 
79  ActsScalar hR = 0.5 * (maxLocY + minLocY);
80  ActsScalar hY = 0.5 * (maxLocY - minLocY);
81  ActsScalar hXminY = minR * sinPhiHalf;
82  ActsScalar hXmaxY = maxR * sinPhiHalf;
83 
84  auto tgTrapezoid =
85  std::make_shared<Acts::TrapezoidBounds>(hXminY, hXmaxY, hY);
86 
87  for (int im = 0; im < m_cfg.discPhiSegments; ++im) {
88  // Get the moduleTransform
89  ActsScalar phi = -M_PI + im * phiStep;
90  auto tgTransform =
91  Transform3(Translation3(hR * std::cos(phi), hR * std::sin(phi),
92  discCenter.z()) *
93  AngleAxis3(phi - 0.5 * M_PI, Vector3::UnitZ()));
94 
95  // Create a new detector element per split
96  auto tgDetectorElement = std::make_shared<Acts::TGeoDetectorElement>(
97  tgIdentifier, tgNode, tgTransform, tgTrapezoid, tgThickness);
98 
99  tgDetectorElements.push_back(tgDetectorElement);
100  }
101  }
102 
103  return tgDetectorElements;
104  }
105  }
106 
107  // Cylinder segments are detected, attempt a split
108  if (m_cfg.cylinderPhiSegments > 0 or m_cfg.cylinderLongitudinalSegments > 0) {
109  if (sf.type() == Acts::Surface::Cylinder and
111  ACTS_DEBUG("- splitting detected for a Cylinder shaped sensor.");
112 
113  std::vector<std::shared_ptr<const Acts::TGeoDetectorElement>>
114  tgDetectorElements = {};
115  tgDetectorElements.reserve(std::abs(m_cfg.cylinderPhiSegments) *
116  std::abs(m_cfg.cylinderLongitudinalSegments));
117 
118  const auto& boundValues = sf.bounds().values();
119  ActsScalar cylinderR = boundValues[Acts::CylinderBounds::eR];
120  ActsScalar cylinderHalfZ =
122 
123  ActsScalar phiStep = 2 * M_PI / m_cfg.cylinderPhiSegments;
124  ActsScalar cosPhiHalf = std::cos(0.5 * phiStep);
125  ActsScalar sinPhiHalf = std::sin(0.5 * phiStep);
126 
127  std::vector<ActsScalar> zValues = {};
128  if (m_cfg.cylinderLongitudinalSegments > 1) {
129  ActsScalar zStep =
130  2 * cylinderHalfZ / m_cfg.cylinderLongitudinalSegments;
131  zValues.reserve(m_cfg.cylinderLongitudinalSegments);
132  for (int ir = 0; ir <= m_cfg.cylinderLongitudinalSegments; ++ir) {
133  zValues.push_back(-cylinderHalfZ + ir * zStep);
134  }
135  } else {
136  zValues = {-cylinderHalfZ, cylinderHalfZ};
137  }
138 
139  ActsScalar planeR = cylinderR * cosPhiHalf;
140  ActsScalar planeHalfX = cylinderR * sinPhiHalf;
141 
142  for (size_t iz = 1; iz < zValues.size(); ++iz) {
143  ActsScalar minZ = zValues[iz - 1];
144  ActsScalar maxZ = zValues[iz];
145 
146  ActsScalar planeZ = 0.5 * (minZ + maxZ);
147  ActsScalar planeHalfY = 0.5 * (maxZ - minZ);
148 
149  auto tgRectangle =
150  std::make_shared<Acts::RectangleBounds>(planeHalfX, planeHalfY);
151 
152  for (int im = 0; im < m_cfg.cylinderPhiSegments; ++im) {
153  // Get the moduleTransform
154  ActsScalar phi = -M_PI + im * phiStep;
155  ActsScalar cosPhi = std::cos(phi);
156  ActsScalar sinPhi = std::sin(phi);
157  ActsScalar planeX = planeR * cosPhi;
158  ActsScalar planeY = planeR * sinPhi;
159 
160  Acts::Vector3 planeCenter(planeX, planeY, planeZ);
161  Acts::Vector3 planeAxisZ = {cosPhi, sinPhi, 0.};
162  Acts::Vector3 planeAxisY{0., 0., 1.};
163  Acts::Vector3 planeAxisX = planeAxisY.cross(planeAxisZ);
164 
165  RotationMatrix3 planeRotation;
166  planeRotation.col(0) = planeAxisX;
167  planeRotation.col(1) = planeAxisY;
168  planeRotation.col(2) = planeAxisZ;
169 
170  // curvilinear surfaces are boundless
171  Transform3 planeTransform{planeRotation};
172  planeTransform.pretranslate(planeCenter);
173 
174  Transform3 tgTransform = planeTransform;
175 
176  // Create a new detector element per split
177  auto tgDetectorElement = std::make_shared<Acts::TGeoDetectorElement>(
178  tgIdentifier, tgNode, tgTransform, tgRectangle, tgThickness);
179 
180  tgDetectorElements.push_back(tgDetectorElement);
181  }
182  }
183  return tgDetectorElements;
184  }
185  }
186  return {tgde};
187 }