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