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