ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TGeoDetectorElement.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TGeoDetectorElement.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-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 
9 #include <boost/algorithm/string.hpp>
10 #include <fstream>
11 #include <iostream>
12 #include <utility>
13 
26 #include "TGeoArb8.h"
27 #include "TGeoBBox.h"
28 #include "TGeoBoolNode.h"
29 #include "TGeoCompositeShape.h"
30 #include "TGeoTrd2.h"
31 #include "TGeoTube.h"
32 
33 using Line2D = Eigen::Hyperplane<double, 2>;
34 
36  const Identifier& identifier, TGeoNode* tGeoDetElement,
37  const TGeoMatrix* mGlobal, const std::string& axes, double scalor,
38  bool isDisc, std::shared_ptr<const Acts::ISurfaceMaterial> material,
39  std::shared_ptr<const Acts::DigitizationModule> digitizationModule)
40  : Acts::IdentifiedDetectorElement(),
41  m_detElement(tGeoDetElement),
42  m_identifier(identifier),
43  m_digitizationModule(std::move(digitizationModule)) {
44  using namespace TGeoPrimitivesHelpers;
45 
46  // create temporary local non const surface (to allow setting the material)
47  std::shared_ptr<Surface> surface = nullptr;
48  // get the placement and orientation in respect to its mother
49  const TGeoMatrix* nodeTransform = (m_detElement->GetMatrix());
50  const Double_t* rotation = nullptr;
51  const Double_t* translation = nullptr;
52 
53  if (mGlobal != nullptr) {
54  // the new combined translation
55  TGeoHMatrix nTransform =
56  TGeoCombiTrans(*mGlobal) * TGeoCombiTrans(*nodeTransform);
57  std::string nName = tGeoDetElement->GetName();
58  std::string suffix = "_transform";
59  nTransform.SetName((nName + suffix).c_str());
60  translation = nTransform.GetTranslation();
61  rotation = nTransform.GetRotationMatrix();
62  } else {
63  translation = (nodeTransform->GetTranslation());
64  rotation = (nodeTransform->GetRotationMatrix());
65  }
66  // Simply call the construct method
67  construct(rotation, translation, axes, scalor, isDisc, std::move(material));
68 }
69 
71  const Identifier& identifier, const TGeoMatrix& transform,
72  TGeoNode* tGeoDetElement, const std::string& axes, double scalor,
73  bool isDisc, std::shared_ptr<const Acts::ISurfaceMaterial> material,
74  std::shared_ptr<const Acts::DigitizationModule> digitizationModule)
75  : Acts::IdentifiedDetectorElement(),
76  m_detElement(tGeoDetElement),
77  m_identifier(identifier),
78  m_digitizationModule(std::move(digitizationModule)) {
79  // get the placement and orientation in respect to its mother
80  const Double_t* rotation = transform.GetRotationMatrix();
81  const Double_t* translation = transform.GetTranslation();
82  // Simply call the construct method
83  construct(rotation, translation, axes, scalor, isDisc, std::move(material));
84 }
85 
87  const Double_t* rotation, const Double_t* translation,
88  const std::string& axes, double scalor, bool isDisc,
89  std::shared_ptr<const Acts::ISurfaceMaterial> material) {
90  using namespace TGeoPrimitivesHelpers;
91 
92  // create temporary local non const surface (to allow setting the material)
93  std::shared_ptr<Surface> surface = nullptr;
94 
95  // create the translation
96  Vector3D colT(scalor * translation[0], scalor * translation[1],
97  scalor * translation[2]);
98  Vector3D colX(rotation[0], rotation[3], rotation[6]);
99  Vector3D colY(rotation[1], rotation[4], rotation[7]);
100  Vector3D colZ(rotation[2], rotation[5], rotation[8]);
101 
102  auto sensor = m_detElement->GetVolume();
103 
104  // Special test for composite shape of silicon
105  auto tgShape = sensor->GetShape();
106  auto compShape = dynamic_cast<TGeoCompositeShape*>(tgShape);
107  if (compShape != nullptr) {
108  auto interNode = dynamic_cast<TGeoIntersection*>(compShape->GetBoolNode());
109  if (interNode != nullptr) {
110  auto baseTube = dynamic_cast<TGeoTubeSeg*>(interNode->GetLeftShape());
111  if (baseTube != nullptr) {
112  m_transform = std::make_shared<const Transform3D>(
113  makeTransform(colX, colY, colZ, colT));
114  double rMin = baseTube->GetRmin() * scalor;
115  double rMax = baseTube->GetRmax() * scalor;
116  auto maskShape = dynamic_cast<TGeoArb8*>(interNode->GetRightShape());
117  if (maskShape != nullptr) {
118  auto maskTransform = interNode->GetRightMatrix();
119  // Get pthe oly vertices
120  const Double_t* polyVrt = maskShape->GetVertices();
121  // the poly has a translation matrix in ROOT
122  // we apply it to the vertices directly
123  const Double_t* polyTrl = nullptr;
124  polyTrl = (maskTransform->GetTranslation());
125  std::vector<Vector2D> vertices;
126  for (unsigned int v = 0; v < 8; v += 2) {
127  Vector2D vtx = Vector2D((polyTrl[0] + polyVrt[v + 0]) * scalor,
128  (polyTrl[1] + polyVrt[v + 1]) * scalor);
129  vertices.push_back(vtx);
130  }
131 
132  std::vector<std::pair<Vector2D, Vector2D>> boundLines;
133  for (size_t i = 0; i < vertices.size(); ++i) {
134  Vector2D a = vertices.at(i);
135  Vector2D b = vertices.at((i + 1) % vertices.size());
136  Vector2D ab = b - a;
137  double phi = VectorHelpers::phi(ab);
138 
139  if (std::abs(phi) > 3 * M_PI / 4. || std::abs(phi) < M_PI / 4.) {
140  if (a.norm() < b.norm()) {
141  boundLines.push_back(std::make_pair(a, b));
142  } else {
143  boundLines.push_back(std::make_pair(b, a));
144  }
145  }
146  }
147 
148  if (boundLines.size() != 2) {
149  throw std::logic_error(
150  "Input DiscPoly bounds type does not have sensible edges.");
151  }
152 
153  Line2D lA =
154  Line2D::Through(boundLines[0].first, boundLines[0].second);
155  Line2D lB =
156  Line2D::Through(boundLines[1].first, boundLines[1].second);
157  Vector2D ix = lA.intersection(lB);
158 
159  const Eigen::Translation3d originTranslation(ix.x(), ix.y(), 0.);
160  const Vector2D originShift = -ix;
161 
162  // Update transform by prepending the origin shift translation
163  m_transform = std::make_shared<const Transform3D>((*m_transform) *
164  originTranslation);
165  // Transform phi line point to new origin and get phi
166  double phi1 =
167  VectorHelpers::phi(boundLines[0].second - boundLines[0].first);
168  double phi2 =
169  VectorHelpers::phi(boundLines[1].second - boundLines[1].first);
170  double phiMax = std::max(phi1, phi2);
171  double phiMin = std::min(phi1, phi2);
172  double phiShift = 0.;
173 
174  // Create the bounds
175  auto annulusBounds = std::make_shared<const AnnulusBounds>(
176  rMin, rMax, phiMin, phiMax, originShift, phiShift);
177 
178  m_thickness = maskShape->GetDZ() * scalor;
179  m_bounds = annulusBounds;
180  surface = Surface::makeShared<DiscSurface>(annulusBounds, *this);
181  }
182  }
183  }
184  }
185 
186  if (surface == nullptr) {
187  // check if it's a box - always true ...
188  TGeoBBox* box = dynamic_cast<TGeoBBox*>(tgShape);
189  // check if it's a trapezoid - unfortunately box is the base of everything
190  TGeoTrd2* trapezoid = dynamic_cast<TGeoTrd2*>(tgShape);
191  // check if it's a tube segment
192  TGeoTubeSeg* tube = dynamic_cast<TGeoTubeSeg*>(tgShape);
193  if (tube != nullptr) {
194  m_transform = std::make_shared<const Transform3D>(
195  makeTransform(colX, colY, colZ, colT));
196  double rMin = tube->GetRmin() * scalor;
197  double rMax = tube->GetRmax() * scalor;
198  double halfZ = tube->GetDz() * scalor;
199 
200  if (isDisc) {
201  // create disc surface
202  m_thickness = halfZ;
203  auto radialBounds = std::make_shared<const RadialBounds>(rMin, rMax);
204  m_bounds = radialBounds;
205  surface = Surface::makeShared<DiscSurface>(radialBounds, *this);
206  } else {
207  // create a cylinder surface
208  m_thickness = std::fabs(rMax - rMin);
209  double radius = (rMin + rMax) * 0.5;
210  auto cylinderBounds =
211  std::make_shared<const CylinderBounds>(radius, halfZ);
212  m_bounds = cylinderBounds;
213  surface = Surface::makeShared<CylinderSurface>(cylinderBounds, *this);
214  }
215  } else {
216  if (boost::iequals(axes, "XYZ")) {
217  // get the sign of the axes
218  int signX = 1;
219  int signY = 1;
220  int signZ = 1;
221  if (islower(axes.at(0)) != 0) {
222  signX = -1;
223  }
224  if (islower(axes.at(1)) != 0) {
225  signY = -1;
226  }
227  if (islower(axes.at(2)) != 0) {
228  signZ = -1;
229  }
230  // the transformation matrix
231  colX *= signX;
232  colY *= signY;
233  colZ *= signZ;
234  m_transform = std::make_shared<const Transform3D>(
235  makeTransform(colX, colY, colZ, colT));
236  if (trapezoid != nullptr) {
237  // bounds with x/y
238  auto trapezoidBounds = std::make_shared<const TrapezoidBounds>(
239  scalor * trapezoid->GetDx1(), scalor * trapezoid->GetDx2(),
240  scalor * 0.5 * (trapezoid->GetDy1() + trapezoid->GetDy2()));
241  // thickness
242  m_thickness = scalor * trapezoid->GetDz();
243  // assign them
244  m_bounds = trapezoidBounds;
245  // create the surface
246  surface = Surface::makeShared<PlaneSurface>(trapezoidBounds, *this);
247  } else {
248  // bounds with x/y
249  auto rectangleBounds = std::make_shared<const RectangleBounds>(
250  scalor * box->GetDX(), scalor * box->GetDY());
251  // thickness
252  m_thickness = scalor * box->GetDZ();
253  // assign them
254  m_bounds = rectangleBounds;
255  // create the surface
256  surface = Surface::makeShared<PlaneSurface>(rectangleBounds, *this);
257  }
258  } else if (boost::iequals(axes, "XZY")) {
259  // next possibility
260  // get the sign of the axes
261  int signX = 1;
262  int signY = 1;
263  int signZ = 1;
264  if (islower(axes.at(0)) != 0) {
265  signX = -1;
266  }
267  if (islower(axes.at(1)) != 0) {
268  signZ = -1;
269  }
270  if (islower(axes.at(2)) != 0) {
271  signY = -1;
272  }
273  // the transformation matrix
274  colX *= signX;
275  colY *= signY;
276  colZ *= signZ;
277  m_transform = std::make_shared<const Transform3D>(
278  makeTransform(colX, colZ, colY, colT));
279  if (trapezoid != nullptr) {
280  // bounds with x/z
281  auto trapezoidBounds = std::make_shared<const TrapezoidBounds>(
282  scalor * trapezoid->GetDx1(), scalor * trapezoid->GetDx2(),
283  scalor * trapezoid->GetDz());
284  // thickness
285  m_thickness =
286  scalor * 0.5 * (trapezoid->GetDy1() + trapezoid->GetDy2());
287  // assign them
288  m_bounds = trapezoidBounds;
289  // create the surface
290  surface = Surface::makeShared<PlaneSurface>(trapezoidBounds, *this);
291  } else {
292  // bounds with x/z
293  auto rectangleBounds = std::make_shared<const RectangleBounds>(
294  scalor * box->GetDX(), scalor * box->GetDZ());
295  // thickness
296  m_thickness = scalor * box->GetDY();
297  // assign them
298  m_bounds = rectangleBounds;
299  // create the surface
300  surface = Surface::makeShared<PlaneSurface>(rectangleBounds, *this);
301  }
302 
303  } else if (boost::iequals(axes, "YZX")) {
304  // next possibility
305  // get the sign of the axes
306  int signX = 1;
307  int signY = 1;
308  int signZ = 1;
309  if (islower(axes.at(0)) != 0) {
310  signY = -1;
311  }
312  if (islower(axes.at(1)) != 0) {
313  signZ = -1;
314  }
315  if (islower(axes.at(2)) != 0) {
316  signX = -1;
317  }
318  // the transformation matrix
319  colX *= signX;
320  colY *= signY;
321  colZ *= signZ;
322  m_transform = std::make_shared<const Transform3D>(
323  makeTransform(colY, colZ, colX, colT));
324  if (trapezoid != nullptr) {
325  // bounds with y/z
326  auto trapezoidBounds = std::make_shared<const TrapezoidBounds>(
327  scalor * trapezoid->GetDy1(), scalor * trapezoid->GetDy2(),
328  scalor * trapezoid->GetDz());
329  // thickness
330  m_thickness =
331  scalor * 0.5 * (trapezoid->GetDx1() + trapezoid->GetDx2());
332  // assign them
333  m_bounds = trapezoidBounds;
334  // create the surface
335  surface = Surface::makeShared<PlaneSurface>(trapezoidBounds, *this);
336  } else {
337  // bounds with y/z
338  auto rectangleBounds = std::make_shared<const RectangleBounds>(
339  scalor * box->GetDY(), scalor * box->GetDZ());
340  // thickness
341  m_thickness = scalor * box->GetDX();
342  // assign them
343  m_bounds = rectangleBounds;
344  // create the surface
345  surface = Surface::makeShared<PlaneSurface>(rectangleBounds, *this);
346  }
347  } else if (boost::iequals(axes, "YXZ")) {
348  // next possibility
349  // get the sign of the axes
350  int signX = 1;
351  int signY = 1;
352  int signZ = 1;
353  if (islower(axes.at(0)) != 0) {
354  signY = -1;
355  }
356  if (islower(axes.at(1)) != 0) {
357  signX = -1;
358  }
359  if (islower(axes.at(2)) != 0) {
360  signZ = -1;
361  }
362  // the transformation matrix
363  colX *= signX;
364  colY *= signY;
365  colZ *= signZ;
366  m_transform = std::make_shared<const Transform3D>(
367  makeTransform(colY, colX, colZ, colT));
368  if (trapezoid != nullptr) {
369  // bounds with y/x
370  auto trapezoidBounds = std::make_shared<const TrapezoidBounds>(
371  scalor * trapezoid->GetDy1(), scalor * trapezoid->GetDy2(),
372  scalor * 0.5 * (trapezoid->GetDx1() + trapezoid->GetDx2()));
373  // thickness
374  m_thickness = scalor * trapezoid->GetDz();
375  // assign them
376  m_bounds = trapezoidBounds;
377  // create the surface
378  surface = Surface::makeShared<PlaneSurface>(trapezoidBounds, *this);
379  } else {
380  // bounds with y/x
381  auto rectangleBounds = std::make_shared<const RectangleBounds>(
382  scalor * box->GetDY(), scalor * box->GetDX());
383  // thickness
384  m_thickness = scalor * box->GetDZ();
385  // assign them
386  m_bounds = rectangleBounds;
387  // create the surface
388  surface = Surface::makeShared<PlaneSurface>(rectangleBounds, *this);
389  }
390  } else if (boost::iequals(axes, "ZYX")) {
391  // next possibility
392  // get the sign of the axes
393  int signX = 1;
394  int signY = 1;
395  int signZ = 1;
396  if (islower(axes.at(0)) != 0) {
397  signZ = -1;
398  }
399  if (islower(axes.at(1)) != 0) {
400  signY = -1;
401  }
402  if (islower(axes.at(2)) != 0) {
403  signX = -1;
404  }
405  // the transformation matrix
406  colX *= signX;
407  colY *= signY;
408  colZ *= signZ;
409  m_transform = std::make_shared<const Transform3D>(
410  makeTransform(colZ, colY, colX, colT));
411  if (trapezoid != nullptr) {
412  // bounds with z/y
413  auto trapezoidBounds = std::make_shared<const TrapezoidBounds>(
414  scalor * trapezoid->GetDz(), scalor * trapezoid->GetDz(),
415  scalor * 0.5 * (trapezoid->GetDy1() + trapezoid->GetDy2()));
416  // thickness
417  m_thickness =
418  scalor * 0.5 * (trapezoid->GetDx1() + trapezoid->GetDx2());
419  // assign them
420  m_bounds = trapezoidBounds;
421  // create the surface
422  surface = Surface::makeShared<PlaneSurface>(trapezoidBounds, *this);
423  } else {
424  // bounds with z/y
425  auto rectangleBounds = std::make_shared<const RectangleBounds>(
426  scalor * box->GetDZ(), scalor * box->GetDY());
427  // thickness
428  m_thickness = scalor * box->GetDX();
429  // assign them
430  m_bounds = rectangleBounds;
431  // create the surface
432  surface = Surface::makeShared<PlaneSurface>(rectangleBounds, *this);
433  }
434  } else {
435  // default is "ZXY"
436  // next possibility
437  // get the sign of the axes
438  int signX = 1;
439  int signY = 1;
440  int signZ = 1;
441  if (islower(axes.at(0)) != 0) {
442  signZ = -1;
443  }
444  if (islower(axes.at(1)) != 0) {
445  signX = -1;
446  }
447  if (islower(axes.at(2)) != 0) {
448  signY = -1;
449  }
450  // the transformation matrix
451  colX *= signX;
452  colY *= signY;
453  colZ *= signZ;
454  m_transform = std::make_shared<const Transform3D>(
455  makeTransform(colZ, colX, colY, colT));
456  if (trapezoid != nullptr) {
457  // bounds with z/x
458  auto trapezoidBounds = std::make_shared<const TrapezoidBounds>(
459  scalor * trapezoid->GetDz(), scalor * trapezoid->GetDz(),
460  scalor * 0.5 * (trapezoid->GetDx1() + trapezoid->GetDx2()));
461  // thickness
462  m_thickness =
463  scalor * 0.5 * (trapezoid->GetDy1() + trapezoid->GetDy2());
464  // assign them
465  m_bounds = trapezoidBounds;
466  // create the surface
467  surface = Surface::makeShared<PlaneSurface>(trapezoidBounds, *this);
468  } else {
469  // bounds with z/x
470  auto rectangleBounds = std::make_shared<const RectangleBounds>(
471  scalor * box->GetDZ(), scalor * box->GetDX());
472  // thickness
473  m_thickness = scalor * box->GetDY();
474  // assign them
475  m_bounds = rectangleBounds;
476  // create the surface
477  surface = Surface::makeShared<PlaneSurface>(rectangleBounds, *this);
478  }
479  }
480  }
481  }
482  // set the asscoiated material (non const method)
483  if (surface != nullptr) {
484  surface->assignSurfaceMaterial(std::move(material));
485  }
486  // set the const member surface
487  m_surface = surface;
488 }
489