ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DD4hepLayerBuilder.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file DD4hepLayerBuilder.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-2019 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 
13 #include "Acts/Geometry/Layer.hpp"
27 #include "Acts/Utilities/Units.hpp"
28 #include "DD4hep/Detector.h"
29 #include "TGeoManager.h"
30 #include "TGeoMatrix.h"
31 
32 #include <boost/algorithm/string.hpp>
33 
36  std::unique_ptr<const Logger> logger)
37  : m_cfg(), m_logger(std::move(logger)) {
38  setConfiguration(config);
39 }
40 
42 
45  m_cfg = config;
46 }
47 
49  const GeometryContext& gctx,
50  const std::vector<dd4hep::DetElement>& dendcapLayers,
51  const std::string& side) const {
52  LayerVector layers;
53  if (dendcapLayers.empty()) {
54  ACTS_VERBOSE(" No layers handed over for " << side << " volume!");
55  } else {
56  ACTS_VERBOSE(" Received layers for " << side
57  << " volume -> creating "
58  "disc layers");
59  // go through layers
60  for (auto& detElement : dendcapLayers) {
61  // prepare the layer surfaces
62  std::vector<std::shared_ptr<const Surface>> layerSurfaces;
63  // access the extension of the layer
64  // at this stage all layer detElements have extension (checked in
65  // ConvertDD4hepDetector)
66  Acts::ActsExtension* detExtension =
67  detElement.extension<Acts::ActsExtension>();
68  // collect the sensitive detector elements possibly contained by the layer
69  resolveSensitive(detElement, layerSurfaces);
70  // access the global transformation matrix of the layer
71  auto transform =
72  convertTransform(&(detElement.nominal().worldTransformation()));
73  // get the shape of the layer
74  TGeoShape* geoShape =
75  detElement.placement().ptr()->GetVolume()->GetShape();
76  // create the proto layer
77  ProtoLayer pl(gctx, layerSurfaces);
78  if (detExtension->hasValue("r", "envelope") &&
79  detExtension->hasValue("z", "envelope")) {
80  // set the values of the proto layer in case enevelopes are handed over
81  pl.envR = {detExtension->getValue("r", "envelope"),
82  detExtension->getValue("r", "envelope")};
83  pl.envZ = {detExtension->getValue("z", "envelope"),
84  detExtension->getValue("z", "envelope")};
85  } else if (geoShape != nullptr) {
86  TGeoTubeSeg* tube = dynamic_cast<TGeoTubeSeg*>(geoShape);
87  if (tube == nullptr) {
88  ACTS_ERROR(" Disc layer has wrong shape - needs to be TGeoTubeSeg!");
89  }
90  // extract the boundaries
91  double rMin = tube->GetRmin() * UnitConstants::cm;
92  double rMax = tube->GetRmax() * UnitConstants::cm;
93  double zMin =
94  (transform->translation() -
95  transform->rotation().col(2) * tube->GetDz() * UnitConstants::cm)
96  .z();
97  double zMax =
98  (transform->translation() +
99  transform->rotation().col(2) * tube->GetDz() * UnitConstants::cm)
100  .z();
101  if (zMin > zMax) {
102  std::swap(zMin, zMax);
103  }
104  // check if layer has surfaces
105  if (layerSurfaces.empty()) {
106  ACTS_VERBOSE(" Disc layer has no senstive surfaces.");
107  // in case no surfaces are handed over the layer thickness will be set
108  // to a default value to allow attaching material layers
109  double z = (zMin + zMax) * 0.5;
110  // create layer without surfaces
111  // manually create a proto layer
112  pl.minZ = (z != 0.) ? z - m_cfg.defaultThickness : 0.;
113  pl.maxZ = (z != 0.) ? z + m_cfg.defaultThickness : 0.;
114  pl.minR = rMin;
115  pl.maxR = rMax;
116  pl.envR = {0., 0.};
117  pl.envZ = {0., 0.};
118  } else {
119  ACTS_VERBOSE(" Disc layer has " << layerSurfaces.size()
120  << " senstive surfaces.");
121  // set the values of the proto layer in case dimensions are given by
122  // geometry
123  pl.envZ = {std::abs(zMin - pl.minZ), std::abs(zMax - pl.maxZ)};
124  pl.envR = {std::abs(rMin - pl.minR), std::abs(rMax - pl.maxR)};
125  }
126  } else {
127  throw std::logic_error(
128  std::string("Layer DetElement: ") + detElement.name() +
129  std::string(" has neither a shape nor tolerances for envelopes "
130  "added to its extension. Please check your detector "
131  "constructor!"));
132  }
133 
134  std::shared_ptr<Layer> endcapLayer = nullptr;
135  // In case the layer is sensitive
136  if (detElement.volume().isSensitive()) {
137  // Create the sensitive surface
138  auto sensitiveSurf = createSensitiveSurface(detElement, true);
139  // Create the surfaceArray
140  std::unique_ptr<Acts::SurfaceArray> sArray =
141  std::make_unique<SurfaceArray>(sensitiveSurf);
142 
143  // create the share disc bounds
144  auto dBounds = std::make_shared<const RadialBounds>(pl.minR, pl.maxR);
145  double thickness = std::fabs(pl.maxZ - pl.minZ);
146  // Create the layer containing the sensitive surface
147  endcapLayer = DiscLayer::create(transform, dBounds, std::move(sArray),
148  thickness, nullptr, Acts::active);
149 
150  } else {
151  endcapLayer = m_cfg.layerCreator->discLayer(
152  gctx, layerSurfaces, m_cfg.bTypeR, m_cfg.bTypePhi, pl, transform,
153  nullptr);
154  }
155  // Add the ProtoMaterial if present
156  addDiscLayerProtoMaterial(detElement, *endcapLayer);
157  // push back created layer
158  layers.push_back(endcapLayer);
159  }
160  }
161  return layers;
162 }
163 
165  const GeometryContext& gctx) const {
166  return endcapLayers(gctx, m_cfg.negativeLayers, "negative");
167 }
168 
170  const GeometryContext& gctx) const {
171  LayerVector layers;
172  if (m_cfg.centralLayers.empty()) {
173  ACTS_VERBOSE(" No layers handed over for central volume!");
174  } else {
175  ACTS_VERBOSE(
176  " Received layers for central volume -> creating "
177  "cylindrical layers");
178  // go through layers
179  for (auto& detElement : m_cfg.centralLayers) {
180  // prepare the layer surfaces
181  std::vector<std::shared_ptr<const Surface>> layerSurfaces;
182  // access the extension of the layer
183  // at this stage all layer detElements have extension (checked in
184  // ConvertDD4hepDetector)
185  Acts::ActsExtension* detExtension =
186  detElement.extension<Acts::ActsExtension>();
187  // collect the sensitive detector elements possibly contained by the layer
188  resolveSensitive(detElement, layerSurfaces);
189  // access the global transformation matrix of the layer
190  auto transform =
191  convertTransform(&(detElement.nominal().worldTransformation()));
192  // get the shape of the layer
193  TGeoShape* geoShape =
194  detElement.placement().ptr()->GetVolume()->GetShape();
195  // create the proto layer
196  ProtoLayer pl(gctx, layerSurfaces);
197  if (detExtension->hasValue("r", "envelope") &&
198  detExtension->hasValue("z", "envelope")) {
199  // set the values of the proto layer in case enevelopes are handed over
200  pl.envR = {detExtension->getValue("r", "envelope"),
201  detExtension->getValue("r", "envelope")};
202  pl.envZ = {detExtension->getValue("z", "envelope"),
203  detExtension->getValue("z", "envelope")};
204  } else if (geoShape != nullptr) {
205  TGeoTubeSeg* tube = dynamic_cast<TGeoTubeSeg*>(geoShape);
206  if (tube == nullptr)
207  ACTS_ERROR(
208  " Cylinder layer has wrong shape - needs to be TGeoTubeSeg!");
209 
210  // extract the boundaries
211  double rMin = tube->GetRmin() * UnitConstants::cm;
212  double rMax = tube->GetRmax() * UnitConstants::cm;
213  double dz = tube->GetDz() * UnitConstants::cm;
214  // check if layer has surfaces
215  if (layerSurfaces.empty()) {
216  // in case no surfaces are handed over the layer thickness will be set
217  // to a default value to allow attaching material layers
218  double r = (rMin + rMax) * 0.5;
219  // create layer without surfaces
220  // manually create a proto layer
221  pl.minR = (r != 0.) ? r - m_cfg.defaultThickness : 0.;
222  pl.maxR = (r != 0.) ? r + m_cfg.defaultThickness : 0.;
223  pl.minZ = -dz;
224  pl.maxZ = dz;
225  pl.envR = {0., 0.};
226  pl.envZ = {0., 0.};
227  } else {
228  // set the values of the proto layer in case dimensions are given by
229  // geometry
230  pl.envZ = {std::abs(-dz - pl.minZ), std::abs(dz - pl.maxZ)};
231  pl.envR = {std::abs(rMin - pl.minR), std::abs(rMax - pl.maxR)};
232  }
233  } else {
234  throw std::logic_error(
235  std::string("Layer DetElement: ") + detElement.name() +
236  std::string(" has neither a shape nor tolerances for envelopes "
237  "added to itÂ¥s extension. Please check your detector "
238  "constructor!"));
239  }
240 
241  double halfZ = (pl.minZ - pl.maxZ) * 0.5;
242 
243  std::shared_ptr<Layer> centralLayer = nullptr;
244  // In case the layer is sensitive
245  if (detElement.volume().isSensitive()) {
246  // Create the sensitive surface
247  auto sensitiveSurf = createSensitiveSurface(detElement);
248  // Create the surfaceArray
249  std::unique_ptr<Acts::SurfaceArray> sArray =
250  std::make_unique<SurfaceArray>(sensitiveSurf);
251 
252  // create the layer
253  double layerR = (pl.minR + pl.maxR) * 0.5;
254  double thickness = std::fabs(pl.maxR - pl.minR);
255  std::shared_ptr<const CylinderBounds> cBounds(
256  new CylinderBounds(layerR, halfZ));
257  // Create the layer containing the sensitive surface
258  centralLayer =
259  CylinderLayer::create(transform, cBounds, std::move(sArray),
260  thickness, nullptr, Acts::active);
261 
262  } else {
263  centralLayer = m_cfg.layerCreator->cylinderLayer(
264  gctx, layerSurfaces, m_cfg.bTypePhi, m_cfg.bTypeZ, pl, transform,
265  nullptr);
266  }
267  // Add the ProtoMaterial if present
268  addCylinderLayerProtoMaterial(detElement, *centralLayer);
269  // push back created layer
270  layers.push_back(centralLayer);
271  }
272  }
273  return layers;
274 }
275 
277  const GeometryContext& gctx) const {
278  return endcapLayers(gctx, m_cfg.positiveLayers, "positive");
279 }
280 
282  const dd4hep::DetElement& detElement,
283  std::vector<std::shared_ptr<const Acts::Surface>>& surfaces) const {
284  const dd4hep::DetElement::Children& children = detElement.children();
285  if (!children.empty()) {
286  for (auto& child : children) {
287  dd4hep::DetElement childDetElement = child.second;
288  if (childDetElement.volume().isSensitive()) {
289  // create the surface
290  surfaces.push_back(createSensitiveSurface(childDetElement, false));
291  }
292  resolveSensitive(childDetElement, surfaces);
293  }
294  }
295 }
296 
297 std::shared_ptr<const Acts::Surface>
299  const dd4hep::DetElement& detElement, bool isDisc) const {
300  // access the possible extension of the DetElement
301  Acts::ActsExtension* detExtension = nullptr;
302  try {
303  detExtension = detElement.extension<Acts::ActsExtension>();
304  } catch (std::runtime_error& e) {
305  ACTS_WARNING("Could not get Acts::Extension");
306  return nullptr;
307  }
308 
309  auto detAxis = detExtension->getType("axes", "definitions");
310  // Create the corresponding detector element !- memory leak --!
311  Acts::DD4hepDetectorElement* dd4hepDetElement =
312  new Acts::DD4hepDetectorElement(detElement, detAxis, UnitConstants::cm,
313  isDisc, nullptr, nullptr);
314 
315  // return the surface
316  return dd4hepDetElement->surface().getSharedPtr();
317 }
318 
319 std::shared_ptr<const Acts::Transform3D>
320 Acts::DD4hepLayerBuilder::convertTransform(const TGeoMatrix* tGeoTrans) const {
321  // get the placement and orientation in respect to its mother
322  const Double_t* rotation = tGeoTrans->GetRotationMatrix();
323  const Double_t* translation = tGeoTrans->GetTranslation();
324  auto transform =
325  std::make_shared<const Transform3D>(TGeoPrimitivesHelpers::makeTransform(
326  Acts::Vector3D(rotation[0], rotation[3], rotation[6]),
327  Acts::Vector3D(rotation[1], rotation[4], rotation[7]),
328  Acts::Vector3D(rotation[2], rotation[5], rotation[8]),
329  Acts::Vector3D(translation[0] * UnitConstants::cm,
330  translation[1] * UnitConstants::cm,
331  translation[2] * UnitConstants::cm)));
332  return (transform);
333 }