31 #include "TGeoManager.h"
37 double layerEnvelopeR,
double layerEnvelopeZ,
double defaultLayerThickness,
38 const std::function<
void(std::vector<dd4hep::DetElement>& detectors)>&
41 std::shared_ptr<const IMaterialDecorator> matDecorator) {
44 ACTS_INFO(
"Translating DD4hep geometry into Acts geometry");
47 std::vector<dd4hep::DetElement> subDetectors;
51 sortSubDetectors(subDetectors);
53 std::list<std::shared_ptr<const ITrackingVolumeBuilder>> volumeBuilders;
56 std::shared_ptr<const CylinderVolumeBuilder> beamPipeVolumeBuilder;
58 for (
auto& subDetector : subDetectors) {
59 ACTS_INFO(
"Translating DD4hep sub detector: " << subDetector.name());
62 subDetector, loggingLevel, bTypePhi, bTypeR, bTypeZ, layerEnvelopeR,
63 layerEnvelopeZ, defaultLayerThickness);
66 if (volBuilder->getConfiguration().buildToRadiusZero) {
68 if (beamPipeVolumeBuilder) {
69 throw std::logic_error(
70 std::string(
"Beampipe has already been set! There can only "
71 "exist one beam pipe. Please check your "
72 "detector construction. Current volume name: ") +
73 volBuilder->getConfiguration().volumeName +
74 std::string(
", name of volume, already set as beam pipe: ") +
75 beamPipeVolumeBuilder->getConfiguration().volumeName);
78 beamPipeVolumeBuilder = volBuilder;
80 volumeBuilders.push_back(volBuilder);
85 if (beamPipeVolumeBuilder) {
86 volumeBuilders.push_back(beamPipeVolumeBuilder);
89 std::vector<std::function<std::shared_ptr<TrackingVolume>(
94 for (
const auto& vb : volumeBuilders) {
95 volumeFactories.push_back(
96 [vb](
const GeometryContext& vgctx,
97 const std::shared_ptr<const TrackingVolume>& inner,
99 return vb->trackingVolume(vgctx, inner);
110 auto trackingGeometryBuilder =
111 std::make_shared<const Acts::TrackingGeometryBuilder>(tgbConfig);
112 return (trackingGeometryBuilder->trackingGeometry(gctx));
118 double layerEnvelopeR,
double layerEnvelopeZ,
119 double defaultLayerThickness) {
124 ACTS_VERBOSE(
"Processing detector element: " << subDetector.name());
130 }
catch (std::runtime_error&
e) {
132 if (subDetector.type() ==
"compound") {
134 << subDetector.name()
135 <<
"' has no ActsExtension and has type compound ");
137 "handling as a compound volume (a hierachy of a "
138 "barrel-endcap structure) and resolving the "
143 std::vector<dd4hep::DetElement> negativeLayers;
145 std::vector<dd4hep::DetElement> centralLayers;
147 std::vector<dd4hep::DetElement> positiveLayers;
153 std::vector<dd4hep::DetElement> compounds;
159 bool nEndCap =
false;
160 bool pEndCap =
false;
162 for (
auto& volumeDetElement : compounds) {
164 << subDetector.name()
165 <<
"'is a compound volume -> resolve now the sub volumes");
168 TGeoShape* geoShape =
169 volumeDetElement.placement().ptr()->GetVolume()->GetShape();
171 if (geoShape !=
nullptr) {
172 zPos = volumeDetElement.placement()
175 ->GetTranslation()[2] *
178 throw std::logic_error(std::string(
"Volume of DetElement: ") +
179 volumeDetElement.name() +
180 std::string(
" has no shape!"));
186 volumeExtension = volumeDetElement.extension<
ActsExtension>();
187 }
catch (std::runtime_error& e) {
188 throw std::logic_error(
189 std::string(
"Current DetElement: ") + volumeDetElement.name() +
190 std::string(
" has no ActsExtension! At this stage it should be a "
191 "detector volume declared as Barrel or Endcap. Please"
192 "check your detector construction."));
195 if (volumeExtension->
hasType(
"endcap",
"detector")) {
197 std::string(
"Subvolume : '") + volumeDetElement.name() +
198 std::string(
"' is a disc volume -> handling as an endcap"));
201 throw std::logic_error(
202 "Negative Endcap was already given for this "
203 "hierachy! Please create a new "
204 "DD4hep_SubDetectorAssembly for the next "
211 if (volumeExtension->
hasType(
"boundary_material")) {
212 if (volumeExtension->
hasValue(
"boundary_material_negative")) {
214 *volumeExtension,
"boundary_material_negative",
217 if (volumeExtension->
hasValue(
"boundary_material_positive")) {
219 *volumeExtension,
"boundary_material_positive",
225 throw std::logic_error(
226 "Positive Endcap was already given for this "
227 "hierachy! Please create a new "
228 "DD4hep_SubDetectorAssembly for the next "
235 if (volumeExtension->
hasType(
"boundary_material")) {
236 if (volumeExtension->
hasValue(
"boundary_material_negative")) {
238 *volumeExtension,
"boundary_material_negative",
241 if (volumeExtension->
hasValue(
"boundary_material_positive")) {
243 *volumeExtension,
"boundary_material_positive",
248 }
else if (volumeExtension->
hasType(
"barrel",
"detector")) {
250 throw std::logic_error(
251 "Barrel was already given for this "
252 "hierachy! Please create a new "
253 "DD4hep_SubDetectorAssembly for the next "
258 << volumeDetElement.name()
259 <<
" is a cylinder volume -> handling as a barrel");
262 if (volumeExtension->
hasType(
"boundary_material")) {
263 if (volumeExtension->
hasValue(
"boundary_material_negative")) {
265 *volumeExtension,
"boundary_material_negative",
268 if (volumeExtension->
hasValue(
"boundary_material_positive")) {
270 *volumeExtension,
"boundary_material_positive",
275 throw std::logic_error(
276 std::string(
"Current DetElement: ") + volumeDetElement.name() +
278 " has wrong ActsExtension! At this stage it should be a "
279 "detector volume declared as Barrel or Endcap. Please "
280 "check your detector construction."));
284 if (volumeExtension->
hasType(
"boundary_material")) {
285 if (volumeExtension->
hasValue(
"boundary_material_inner")) {
287 *volumeExtension,
"boundary_material_inner",
290 if (volumeExtension->
hasValue(
"boundary_material_outer")) {
292 *volumeExtension,
"boundary_material_outer",
298 if ((pEndCap && !nEndCap) || (!pEndCap && nEndCap)) {
299 throw std::logic_error(
300 "Only one Endcap is given for the current "
301 "hierarchy! Endcaps should always occur in "
302 "pairs. Please check your detector "
307 auto surfaceArrayCreator =
308 std::make_shared<const Acts::SurfaceArrayCreator>(
313 auto layerCreator = std::make_shared<const Acts::LayerCreator>(
318 lbConfig.layerCreator = layerCreator;
319 lbConfig.negativeLayers = negativeLayers;
320 lbConfig.centralLayers = centralLayers;
321 lbConfig.positiveLayers = positiveLayers;
322 lbConfig.bTypePhi = bTypePhi;
323 lbConfig.bTypeR = bTypeR;
324 lbConfig.bTypeZ = bTypeZ;
325 lbConfig.defaultThickness = defaultLayerThickness;
326 auto dd4hepLayerBuilder = std::make_shared<const Acts::DD4hepLayerBuilder>(
332 dd4hep::Material ddmaterial = subDetector.volume().material();
333 auto volumeMaterial =
334 std::make_shared<const Acts::HomogeneousVolumeMaterial>(
Acts::Material(
335 ddmaterial.radLength(), ddmaterial.intLength(), ddmaterial.A(),
336 ddmaterial.Z(), ddmaterial.density()));
341 cvbConfig.
layerEnvelopeR = std::make_pair(layerEnvelopeR, layerEnvelopeR);
348 auto cylinderVolumeBuilder =
349 std::make_shared<const Acts::CylinderVolumeBuilder>(
353 return cylinderVolumeBuilder;
355 }
else if ((subDetExtension !=
nullptr) &&
356 (subDetExtension->hasType(
"passive cylinder",
"layer") ||
357 subDetExtension->hasType(
"beampipe",
"layer"))) {
359 <<
" - building a passive cylinder.");
360 if (subDetExtension->hasType(
"beampipe",
"layer")) {
361 ACTS_VERBOSE(
"This is the beam pipe - will be built to r -> 0.");
365 TGeoShape* geoShape =
366 subDetector.placement().ptr()->GetVolume()->GetShape();
367 TGeoTubeSeg* tube =
dynamic_cast<TGeoTubeSeg*
>(geoShape);
368 if (tube ==
nullptr) {
369 throw std::logic_error(
370 "Cylinder has wrong shape - needs to be TGeoTubeSeg!");
377 "Extracting cylindrical volume bounds ( rmin / rmax / "
379 << rMin <<
" / " << rMax <<
" / " << halfZ <<
" )");
381 std::shared_ptr<Acts::ISurfaceMaterial> plMaterial =
nullptr;
382 if (subDetExtension->hasType(
"layer_material")) {
385 *subDetExtension,
"layer_material_representing",
396 auto pcLayerBuilder = std::make_shared<const Acts::PassiveLayerBuilder>(
412 auto pcVolumeBuilder = std::make_shared<const Acts::CylinderVolumeBuilder>(
416 return pcVolumeBuilder;
418 }
else if ((subDetExtension !=
nullptr) &&
419 subDetExtension->hasType(
"barrel",
"detector")) {
421 << subDetector.name()
422 <<
" is a (sensitive) Barrel volume - building barrel.");
424 std::vector<dd4hep::DetElement> centralLayers, centralVolumes;
429 auto surfaceArrayCreator =
430 std::make_shared<const Acts::SurfaceArrayCreator>(
435 auto layerCreator = std::make_shared<const Acts::LayerCreator>(
440 lbConfig.layerCreator = layerCreator;
441 lbConfig.centralLayers = centralLayers;
442 lbConfig.bTypePhi = bTypePhi;
443 lbConfig.bTypeZ = bTypeZ;
444 lbConfig.defaultThickness = defaultLayerThickness;
445 auto dd4hepLayerBuilder = std::make_shared<const Acts::DD4hepLayerBuilder>(
454 auto dd4hepVolumeBuilder =
455 std::make_shared<const Acts::DD4hepVolumeBuilder>(
463 TGeoShape* geoShape =
464 subDetector.placement().ptr()->GetVolume()->GetShape();
466 if (geoShape ==
nullptr) {
467 throw std::logic_error(std::string(
"Volume of DetElement: ") +
469 std::string(
" has no a shape!"));
474 dd4hep::Material ddmaterial = subDetector.volume().material();
475 auto volumeMaterial =
476 std::make_shared<const Acts::HomogeneousVolumeMaterial>(
Acts::Material(
477 ddmaterial.radLength(), ddmaterial.intLength(), ddmaterial.A(),
478 ddmaterial.Z(), ddmaterial.density()));
479 cvbConfig.
layerEnvelopeR = std::make_pair(layerEnvelopeR, layerEnvelopeR);
487 auto cylinderVolumeBuilder =
488 std::make_shared<const Acts::CylinderVolumeBuilder>(
492 return cylinderVolumeBuilder;
496 "Subdetector with name : '"
497 << subDetector.name()
498 <<
"' has wrong ActsExtension for translation and is not of type "
499 "'compound'. If you want to have this DetElement be translated "
500 "into the tracking geometry you need add the right "
501 "ActsExtension (at this stage the subvolume needs to be "
502 "declared as beampipe or barrel) or if it is a compound "
503 "DetElement (containing a barrel-endcap hierarchy), the type "
504 "needs to be set to 'compound'.");
514 auto layerArrayCreator = std::make_shared<const Acts::LayerArrayCreator>(
518 auto trackingVolumeArrayCreator =
519 std::make_shared<const Acts::TrackingVolumeArrayCreator>(
525 cvhConfig.trackingVolumeArrayCreator = trackingVolumeArrayCreator;
526 auto cylinderVolumeHelper =
527 std::make_shared<const Acts::CylinderVolumeHelper>(
531 return cylinderVolumeHelper;
535 std::vector<dd4hep::DetElement>& compounds) {
536 const dd4hep::DetElement::Children& children = detElement.children();
537 for (
auto& child : children) {
538 dd4hep::DetElement childDetElement = child.second;
542 }
catch (std::runtime_error&
e) {
544 if ((detExtension !=
nullptr) &&
545 (detExtension->
hasType(
"barrel",
"detector") ||
546 detExtension->
hasType(
"endcap",
"detector"))) {
547 compounds.push_back(childDetElement);
555 std::vector<dd4hep::DetElement>& subdetectors) {
556 const dd4hep::DetElement::Children& children = detElement.children();
557 for (
auto& child : children) {
558 dd4hep::DetElement childDetElement = child.second;
562 }
catch (std::runtime_error&
e) {
563 if (childDetElement.type() ==
"compound") {
564 subdetectors.push_back(childDetElement);
568 if ((detExtension !=
nullptr) &&
569 (detExtension->
hasType(
"barrel",
"detector") ||
570 detExtension->
hasType(
"beampipe",
"layer"))) {
571 subdetectors.push_back(childDetElement);
579 std::vector<dd4hep::DetElement>& layers) {
580 const dd4hep::DetElement::Children& children = detElement.children();
581 for (
auto& child : children) {
582 dd4hep::DetElement childDetElement = child.second;
586 }
catch (std::runtime_error&
e) {
588 if ((detExtension !=
nullptr) && detExtension->
hasType(
"layer")) {
589 layers.push_back(childDetElement);
597 std::vector<dd4hep::DetElement>& volumes) {
598 const dd4hep::DetElement::Children& children = detElement.children();
599 for (
auto& child : children) {
600 dd4hep::DetElement childDetElement = child.second;
604 }
catch (std::runtime_error&
e) {
606 if ((detExtension !=
nullptr) && detExtension->
hasType(
"volume")) {
607 volumes.push_back(childDetElement);