Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CartesianSegmentation.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CartesianSegmentation.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2016-2018 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 // CartesianSegmentation.cpp, Acts project
12 
14 
19 
20 #include <algorithm>
21 #include <cmath>
22 #include <utility>
23 
25  const std::shared_ptr<const PlanarBounds>& mBounds, size_t numCellsX,
26  size_t numCellsY)
27  : m_activeBounds(mBounds), m_binUtility(nullptr) {
28  auto mutableBinUtility = std::make_shared<BinUtility>(
29  numCellsX, -mBounds->boundingBox().halfLengthX(),
30  mBounds->boundingBox().halfLengthX(), Acts::open, Acts::binX);
31  (*mutableBinUtility) +=
32  BinUtility(numCellsY, -mBounds->boundingBox().halfLengthY(),
33  mBounds->boundingBox().halfLengthY(), Acts::open, Acts::binY);
34  m_binUtility = std::const_pointer_cast<const BinUtility>(mutableBinUtility);
35 }
36 
38  std::shared_ptr<const BinUtility> bUtility,
39  std::shared_ptr<const PlanarBounds> mBounds)
40  : m_activeBounds(std::move(mBounds)), m_binUtility(std::move(bUtility)) {
41  if (!m_activeBounds) {
42  m_activeBounds = std::make_shared<const RectangleBounds>(
43  m_binUtility->max(0), m_binUtility->max(1));
44  }
45 }
46 
48 
50  SurfacePtrVector& boundarySurfaces, SurfacePtrVector& segmentationSurfacesX,
51  SurfacePtrVector& segmentationSurfacesY, double halfThickness,
52  int readoutDirection, double lorentzAngle) const {
53  // may be needed throughout
54  double lorentzAngleTan = tan(lorentzAngle);
55  double lorentzPlaneShiftX = halfThickness * lorentzAngleTan;
56 
57  // (A) --- top/bottom surfaces
58  // -----------------------------------------------------------
59  // let's create the top/botten surfaces first - we call them readout / counter
60  // readout
61  // there are some things to consider
62  // - they share the RectangleBounds only if the lorentzAngle is 0
63  // otherwise only the readout surface has full length bounds like the module
64  std::shared_ptr<const PlanarBounds> moduleBounds(
65  new RectangleBounds(m_activeBounds->boundingBox()));
66  // - they are separated by half a thickness in z
67  auto readoutPlaneTransform = Transform3::Identity();
68  auto counterPlaneTransform = Transform3::Identity();
69  // readout and counter readout bounds, the bounds of the readout plane are
70  // like the active ones
71  std::shared_ptr<const PlanarBounds> readoutPlaneBounds = moduleBounds;
72  std::shared_ptr<const PlanarBounds> counterPlaneBounds(nullptr);
73  // the transform of the readout plane is always centric
74  readoutPlaneTransform.translation() =
75  Vector3(0., 0., readoutDirection * halfThickness);
76  // no lorentz angle and everything is straight-forward
77  if (lorentzAngle == 0.) {
78  counterPlaneBounds = moduleBounds;
79  counterPlaneTransform.translation() =
80  Vector3(0., 0., -readoutDirection * halfThickness);
81  } else {
82  // lorentz reduced Bounds
83  double lorentzReducedHalfX =
84  m_activeBounds->boundingBox().halfLengthX() - fabs(lorentzPlaneShiftX);
85  std::shared_ptr<const PlanarBounds> lorentzReducedBounds(
86  new RectangleBounds(lorentzReducedHalfX,
87  m_activeBounds->boundingBox().halfLengthY()));
88  counterPlaneBounds = lorentzReducedBounds;
89  // now we shift the counter plane in position - this depends on lorentz
90  // angle
91  double counterPlaneShift = -readoutDirection * lorentzPlaneShiftX;
92  counterPlaneTransform.translation() =
93  Vector3(counterPlaneShift, 0., -readoutDirection * halfThickness);
94  }
95  // - build the readout & counter readout surfaces
96  boundarySurfaces.push_back(Surface::makeShared<PlaneSurface>(
97  readoutPlaneTransform, readoutPlaneBounds));
98  boundarySurfaces.push_back(Surface::makeShared<PlaneSurface>(
99  counterPlaneTransform, counterPlaneBounds));
100 
101  // (B) - bin X and lorentz surfaces
102  // -----------------------------------------------------------
103  // easy stuff first, constant pitch size and
104  double pitchX =
105  2. * m_activeBounds->boundingBox().halfLengthX() / m_binUtility->bins(0);
106 
107  // now, let's create the shared bounds of all surfaces marking x bins - choice
108  // fixes orientation of the matrix
109  std::shared_ptr<const PlanarBounds> xBinBounds(new RectangleBounds(
110  m_activeBounds->boundingBox().halfLengthY(), halfThickness));
111  // now, let's create the shared bounds of all surfaces marking lorentz planes
112  double lorentzPlaneHalfX = std::abs(halfThickness / cos(lorentzAngle));
113  // the bounds of the lorentz plane
114  std::shared_ptr<const PlanarBounds> lorentzPlaneBounds =
115  (lorentzAngle == 0.)
116  ? xBinBounds
117  : std::shared_ptr<const PlanarBounds>(
118  new RectangleBounds(m_activeBounds->boundingBox().halfLengthY(),
119  lorentzPlaneHalfX));
120 
121  // now the rotation matrix for the xBins
122  RotationMatrix3 xBinRotationMatrix;
123  xBinRotationMatrix.col(0) = Vector3::UnitY();
124  xBinRotationMatrix.col(1) = Vector3::UnitZ();
125  xBinRotationMatrix.col(2) = Vector3::UnitX();
126  // now the lorentz plane rotation should be the xBin rotation, rotated by the
127  // lorentz angle around y
128  RotationMatrix3 lorentzPlaneRotationMatrix =
129  (lorentzAngle != 0.)
130  ? xBinRotationMatrix * AngleAxis3(lorentzAngle, Vector3::UnitX())
131  : xBinRotationMatrix;
132 
133  // reserve, it's always (number of bins-1) as the boundaries are within the
134  // boundarySurfaces
135  segmentationSurfacesX.reserve(m_binUtility->bins(0));
136  // create and fill them
137  for (size_t ibinx = 0; ibinx <= m_binUtility->bins(0); ++ibinx) {
138  // the current step x position
139  double cPosX =
140  -m_activeBounds->boundingBox().halfLengthX() + ibinx * pitchX;
141  // (i) this is the low/high boundary --- ( ibin == 0/m_binUtility->bins(0) )
142  if ((ibinx == 0u) || ibinx == m_binUtility->bins(0)) {
143  // check if it is a straight boundary or not: always straight for no
144  // lorentz angle, and either the first boundary or the last depending on
145  // lorentz and readout
146  bool boundaryStraight =
147  (lorentzAngle == 0. ||
148  ((ibinx == 0u) && readoutDirection * lorentzAngle > 0.) ||
149  (ibinx == m_binUtility->bins(0) &&
150  readoutDirection * lorentzAngle < 0));
151  // set the low boundary parameters : position & rotation
152  Vector3 boundaryXPosition =
153  boundaryStraight
154  ? Vector3(cPosX, 0., 0.)
155  : Vector3(cPosX - readoutDirection * lorentzPlaneShiftX, 0., 0.);
156  // rotation of the boundary: straight or lorentz
157  const RotationMatrix3& boundaryXRotation =
158  boundaryStraight ? xBinRotationMatrix : lorentzPlaneRotationMatrix;
159  // build the rotation from it
160  auto boundaryXTransform =
161  Transform3(Translation3(boundaryXPosition) * boundaryXRotation);
162  // the correct bounds for this
163  std::shared_ptr<const PlanarBounds> boundaryXBounds =
164  boundaryStraight ? xBinBounds : lorentzPlaneBounds;
165  // boundary surfaces
166  boundarySurfaces.push_back(Surface::makeShared<PlaneSurface>(
167  boundaryXTransform, boundaryXBounds));
168  // (ii) this is the in between bins --- ( 1 <= ibin < m_mbnsX )
169  } else {
170  // shift by the lorentz angle
171  Vector3 lorentzPlanePosition(
172  cPosX - readoutDirection * lorentzPlaneShiftX, 0., 0.);
173  auto lorentzPlaneTransform = Transform3(
174  Translation3(lorentzPlanePosition) * lorentzPlaneRotationMatrix);
175  // lorentz plane surfaces
176  segmentationSurfacesX.push_back(Surface::makeShared<PlaneSurface>(
177  lorentzPlaneTransform, lorentzPlaneBounds));
178  }
179  }
180 
181  // (C) - bin Y surfaces - everything is defined
182  // -----------------------------------------------------------
183  // now the rotation matrix for the yBins - anticyclic
184  RotationMatrix3 yBinRotationMatrix;
185  yBinRotationMatrix.col(0) = Vector3::UnitX();
186  yBinRotationMatrix.col(1) = Vector3::UnitZ();
187  yBinRotationMatrix.col(2) = Vector3(0., -1., 0.);
188  // easy stuff first, constant pitch in Y
189  double pitchY =
190  2. * m_activeBounds->boundingBox().halfLengthY() / m_binUtility->bins(1);
191  // let's create the shared bounds of all surfaces marking y bins
192  std::shared_ptr<const PlanarBounds> yBinBounds(new RectangleBounds(
193  m_activeBounds->boundingBox().halfLengthX(), halfThickness));
194  // reserve, it's always (number of bins-1) as the boundaries are within the
195  // boundarySurfaces
196  segmentationSurfacesY.reserve(m_binUtility->bins(1));
197  for (size_t ibiny = 0; ibiny <= m_binUtility->bins(1); ++ibiny) {
198  // the position of the bin surface
199  double binPosY =
200  -m_activeBounds->boundingBox().halfLengthY() + ibiny * pitchY;
201  Vector3 binSurfaceCenter(0., binPosY, 0.);
202  // the binning transform
203  auto binTransform =
204  Transform3(Translation3(binSurfaceCenter) * yBinRotationMatrix);
205  // these are the boundaries
206  if (ibiny == 0 || ibiny == m_binUtility->bins(1)) {
207  boundarySurfaces.push_back(
208  Surface::makeShared<PlaneSurface>(binTransform, yBinBounds));
209  } else { // these are the bin boundaries
210  segmentationSurfacesY.push_back(
211  Surface::makeShared<PlaneSurface>(binTransform, yBinBounds));
212  }
213  }
214 }
215 
217  const DigitizationCell& dCell) const {
218  double bX = m_binUtility->bins(0) > 1
219  ? m_binUtility->binningData()[0].center(dCell.channel0)
220  : 0.;
221  double bY = m_binUtility->bins(1) > 1
222  ? m_binUtility->binningData()[1].center(dCell.channel1)
223  : 0.;
224  return Vector2(bX, bY);
225 }
226 
230  const Vector3& startStep, const Vector3& endStep, double halfThickness,
231  int readoutDirection, double lorentzAngle) const {
232  Vector3 stepCenter = 0.5 * (startStep + endStep);
233  // take the full drift length
234  // this is the absolute drift in z
235  double driftInZ = halfThickness - readoutDirection * stepCenter.z();
236  // this is the absolute drift length
237  double driftLength = driftInZ / cos(lorentzAngle);
238  // project to parameter the readout surface
239  double lorentzDeltaX = readoutDirection * driftInZ * tan(lorentzAngle);
240  // the projected center, it has the lorentz shift applied
241  Vector2 stepCenterProjected(stepCenter.x() + lorentzDeltaX, stepCenter.y());
242  // the cell & its center
243  Acts::DigitizationCell dCell = cell(stepCenterProjected);
244  Vector2 cellCenter = cellPosition(dCell);
245  // we are ready to return what we have
246  return DigitizationStep((endStep - startStep).norm(), driftLength, dCell,
247  startStep, endStep, stepCenterProjected, cellCenter);
248 }