ATLAS Offline Software
Loading...
Searching...
No Matches
ActsTrk::ItkBlueprintNodeBuilder Class Reference

Helper class to build the ItkBlueprint node It adds the system as a node to the Blueprint. More...

#include <ItkBlueprintNodeBuilder.h>

Inheritance diagram for ActsTrk::ItkBlueprintNodeBuilder:
Collaboration diagram for ActsTrk::ItkBlueprintNodeBuilder:

Public Member Functions

StatusCode initialize () override
std::shared_ptr< Acts::BlueprintNode > buildBlueprintNode (const Acts::GeometryContext &gctx, std::shared_ptr< Acts::BlueprintNode > &&child) override
 Build the Itk Blueprint Node.

Private Member Functions

void buildItkStripBlueprintNode (const Acts::GeometryContext &gctx, Acts::BlueprintNode &node)
void buildItkPixelBlueprintNode (const Acts::GeometryContext &gctx, Acts::BlueprintNode &node)

Private Attributes

const InDetDD::SiDetectorManagerm_itkPixelMgr {nullptr}
const InDetDD::SiDetectorManagerm_itkStripMgr {nullptr}
std::shared_ptr< ActsElementVectorm_elementStore {nullptr}
Gaudi::Property< bool > m_doEndcapLayerMerging
Gaudi::Property< bool > m_buildPixel {this, "buildPixel", true}
Gaudi::Property< bool > m_buildStrip {this, "buildStrip", true}

Detailed Description

Helper class to build the ItkBlueprint node It adds the system as a node to the Blueprint.

Definition at line 19 of file ItkBlueprintNodeBuilder.h.

Member Function Documentation

◆ buildBlueprintNode()

std::shared_ptr< Acts::BlueprintNode > ActsTrk::ItkBlueprintNodeBuilder::buildBlueprintNode ( const Acts::GeometryContext & gctx,
std::shared_ptr< Acts::BlueprintNode > && child )
override

Build the Itk Blueprint Node.

Parameters
gctxGeometry context
childOptional beam pipe node to nest inside the ITk AxisR container.

Definition at line 206 of file ItkBlueprintNodeBuilder.cxx.

208 {
209
210 auto itkNode =
211 std::make_shared<Acts::CylinderContainerBlueprintNode>(
212 "itkNode", AxisZ);
213 itkNode->setAttachmentStrategy(AttachmentStrategy::Gap);
214 itkNode->setResizeStrategy(ResizeStrategy::Gap);
215
216 auto& itk = itkNode->addCylinderContainer("ItkNodeMain", AxisR);
217 itk.setAttachmentStrategy(AttachmentStrategy::Gap);
218 itk.setResizeStrategy(ResizeStrategy::Gap);
219
220 itk.addMaterial("ItkNodeMain_Material", [&](auto& mat) {
221 if (m_buildStrip) {
222 mat.configureFace(NegativeDisc,
223 AxisSpec::DeferredEquidistant(20, AxisR),
224 AxisSpec::DeferredEquidistant(40, AxisPhi));
225 mat.configureFace(PositiveDisc,
226 AxisSpec::DeferredEquidistant(20, AxisR),
227 AxisSpec::DeferredEquidistant(40, AxisPhi));
228 }
229
230 auto& innerContainer = mat.addCylinderContainer("ITkInnerContainer", AxisR);
231
232 // Beam pipe is passed in as an optional child from BeamPipeBlueprintNodeBuilder
233 if (childNode) {
234 innerContainer.addChild(std::move(childNode));
235 }
236
237 if (m_buildPixel) {
238 buildItkPixelBlueprintNode(gctx, innerContainer);
239 }
240 if (m_buildStrip) {
241 buildItkStripBlueprintNode(gctx, innerContainer);
242 }
243 });
244
245 return itkNode;
246}
void buildItkStripBlueprintNode(const Acts::GeometryContext &gctx, Acts::BlueprintNode &node)
void buildItkPixelBlueprintNode(const Acts::GeometryContext &gctx, Acts::BlueprintNode &node)

◆ buildItkPixelBlueprintNode()

void ActsTrk::ItkBlueprintNodeBuilder::buildItkPixelBlueprintNode ( const Acts::GeometryContext & gctx,
Acts::BlueprintNode & node )
private

Definition at line 248 of file ItkBlueprintNodeBuilder.cxx.

250 {
251
252 // Get ITkPixel parameters from detector manager
253 if (!m_itkPixelMgr) {
254 ATH_MSG_ERROR("ITkPixel manager not available");
255 throw std::runtime_error("ITkPixel manager not available");
256 }
257
258 ATH_MSG_DEBUG("Detector manager has "
259 << m_itkPixelMgr->getDetectorElementCollection()->size()
260 << " elements");
261
262 std::vector<std::shared_ptr<ActsDetectorElement>> elements;
263
265 for (const auto* element : *m_itkPixelMgr->getDetectorElementCollection()) {
266 const InDetDD::SiDetectorElement* siDetElement =
267 dynamic_cast<const InDetDD::SiDetectorElement*>(element);
268 if (siDetElement == nullptr) {
269 ATH_MSG_ERROR("Detector element was nullptr");
270 throw std::runtime_error{"Corrupt detector element collection"};
271 }
272 elements.push_back(std::make_shared<ActsDetectorElement>(*siDetElement));
273 }
274 ATH_MSG_VERBOSE("Retrieved " << elements.size() << " elements");
275
276 // Copy to service level store to extend lifetime
277 m_elementStore->vector().insert(m_elementStore->vector().end(),
278 elements.begin(), elements.end());
279
280 // Inner pixel: 2 innermost barrel layers + inner endcap disks
281 auto& innerPixel = node.addCylinderContainer("InnerPixel", AxisR);
282 innerPixel.setAttachmentStrategy(AttachmentStrategy::Gap);
283 innerPixel.setResizeStrategy(ResizeStrategy::Gap);
284
285 innerPixel.addMaterial("InnerPixelMaterial", [&](auto& mat) {
286 mat.configureFace(OuterCylinder,
287 AxisSpec::DeferredEquidistant(20, AxisRPhi),
288 AxisSpec::DeferredEquidistant(20, AxisZ));
289 mat.configureFace(InnerCylinder,
290 AxisSpec::DeferredEquidistant(20, AxisRPhi),
291 AxisSpec::DeferredEquidistant(20, AxisZ));
292
293 auto& innerPixelContainer = mat.addCylinderContainer("InnerPixel", AxisZ);
294
295 // Add barrel container
296 auto& barrelGeoId = innerPixelContainer.withGeometryIdentifier();
297 barrelGeoId.setAllVolumeIdsTo(s_innerPixelVolumeId)
298 .incrementLayerIds(1)
299 .sortBy([](auto& a, auto& b) {
300 auto& boundsA =
301 dynamic_cast<const Acts::CylinderVolumeBounds&>(a.volumeBounds());
302 auto& boundsB =
303 dynamic_cast<const Acts::CylinderVolumeBounds&>(b.volumeBounds());
304
305 using enum Acts::CylinderVolumeBounds::BoundValues;
306 double aMidR = (boundsA.get(eMinR) + boundsA.get(eMaxR)) / 2.0;
307 double bMidR = (boundsB.get(eMinR) + boundsB.get(eMaxR)) / 2.0;
308
309 return aMidR < bMidR;
310 });
311
312 auto& brl_mat =
313 barrelGeoId.addMaterial("InnerPixel_Material", [&](auto& material) {
314 material.configureFace(NegativeDisc,
315 AxisSpec::DeferredEquidistant(10, AxisR),
316 AxisSpec::DeferredEquidistant(10, AxisPhi));
317 material.configureFace(PositiveDisc,
318 AxisSpec::DeferredEquidistant(10, AxisR),
319 AxisSpec::DeferredEquidistant(10, AxisPhi));
320 });
321 auto& barrel = brl_mat.addCylinderContainer("InnerPixel_Brl", AxisR);
322
323 barrel.setAttachmentStrategy(AttachmentStrategy::Gap);
324 barrel.setResizeStrategy(ResizeStrategy::Gap);
325
326 std::map<int, std::vector<std::shared_ptr<Acts::Surface>>> layers{};
327
328 for (auto& element : elements) {
329 IdentityHelper id = element->identityHelper();
330 if (id.bec() != 0) {
331 continue;
332 }
333
334 if (id.layer_disk() >= 2) {
335 continue;
336 }
337
338 int elementLayer = id.layer_disk();
339 layers[elementLayer].push_back(element->surface().getSharedPtr());
340 }
341
342 ATH_MSG_DEBUG("Adding " << layers.size() << " layers to InnerPixel barrel");
343
344 for (const auto& [ilayer, surfaces] : layers) {
345 ATH_MSG_DEBUG("- Layer " << ilayer << " has " << surfaces.size()
346 << " surfaces");
347
348 barrel.addMaterial(
349 std::format("InnerPixel_Brl_{}_Material", ilayer), [&](auto& lmat) {
350 lmat.configureFace(OuterCylinder,
351 AxisSpec::DeferredEquidistant(40, AxisRPhi),
352 AxisSpec::DeferredEquidistant(20, AxisZ));
353
354 auto& layer =
355 lmat.addLayer(std::format("InnerPixel_Brl_{}", ilayer));
356
357 layer.setNavigationPolicyFactory(
358 Acts::NavigationPolicyFactory{}
359 .add<Acts::SurfaceArrayNavigationPolicy>(
360 Acts::SurfaceArrayNavigationPolicy::Config{
361 .layerType = Cylinder,
362 .bins = {30, 10}})
363 .add<Acts::TryAllNavigationPolicy>(
364 Acts::TryAllNavigationPolicy::Config{.sensitives =
365 false})
366 .asUniquePtr());
367
368 layer.setSurfaces(surfaces);
369 layer.setEnvelope(Acts::ExtentEnvelope{{
370 .z = {5_mm, 5_mm},
371 .r = {2_mm, 2_mm},
372 }});
373 });
374 }
375
376 // Add endcap containers
377 for (int bec : {-2, 2}) {
378 std::string s = bec > 0 ? "p" : "n";
379 auto& ecGeoId = innerPixelContainer.withGeometryIdentifier();
380 ecGeoId.setAllVolumeIdsTo(s_innerPixelVolumeId + std::floor(bec / 2))
381 .incrementLayerIds(1);
382 auto& ec = ecGeoId.addCylinderContainer("InnerPixel_" + s + "EC", AxisZ);
383 ec.setAttachmentStrategy(AttachmentStrategy::Gap);
384 ec.setResizeStrategy(ResizeStrategy::Gap);
385
386 std::map<std::tuple<int, int, int>,
387 std::vector<std::shared_ptr<Acts::Surface>>>
388 initialLayers{};
389
390 for (auto& element : elements) {
391 IdentityHelper id = element->identityHelper();
392 if (id.bec() * bec <= 0) {
393 continue;
394 }
395
396 if (id.layer_disk() >= 3) {
397 continue;
398 }
399
400 std::tuple<int, int, int> key{id.bec(), id.layer_disk(),
401 id.eta_module()};
402 initialLayers[key].push_back(element->surface().getSharedPtr());
403 }
404
405 ATH_MSG_DEBUG("Found " << initialLayers.size()
406 << " initial layers to InnerPixel " << s << "EC");
407
408 std::vector<LayerData> protoLayers;
409 protoLayers.reserve(initialLayers.size());
410
411 for (const auto& [key, surfaces] : initialLayers) {
412 auto& layer = protoLayers.emplace_back(gctx, surfaces);
413 layer.protoLayer.envelope[AxisR] = {2_mm, 2_mm};
414 layer.protoLayer.envelope[AxisZ] = {1_mm, 1_mm};
415 }
416
417 std::ranges::sort(protoLayers,
418 [](const LayerData& a, const LayerData& b) {
419 return std::abs(a.protoLayer.medium(AxisZ)) <
420 std::abs(b.protoLayer.medium(AxisZ));
421 });
422
423 ATH_MSG_DEBUG("Found " << protoLayers.size() << " initial layers");
424
425 std::vector<LayerData> mergedLayers;
427 mergedLayers = mergeLayers(gctx, std::move(protoLayers));
428 } else {
429 mergedLayers = std::move(protoLayers);
430 }
431
432 ATH_MSG_DEBUG("After merging: " << mergedLayers.size() << " layers");
433
434 for (const auto [key, pl] : Acts::enumerate(mergedLayers)) {
435 ATH_MSG_DEBUG("- Layer " << key << " has " << pl.surfaces.size()
436 << " surfaces");
437
438 pl.protoLayer.medium(AxisZ);
439 auto layerName = std::format("InnerPixel_{}EC_{}", key, s);
440
441 auto addLayer = [&layerName, &pl](auto& parent) {
442 auto& layer = parent.addLayer(layerName);
443
444 layer.setNavigationPolicyFactory(
445 Acts::NavigationPolicyFactory{}
446 .add<Acts::SurfaceArrayNavigationPolicy>(
447 Acts::SurfaceArrayNavigationPolicy::Config{
448 .layerType = Disc,
449 .bins = {30, 30}})
450 .add<Acts::TryAllNavigationPolicy>(
451 Acts::TryAllNavigationPolicy::Config{.sensitives = false})
452 .asUniquePtr());
453
454 layer.setSurfaces(pl.surfaces);
455 layer.setEnvelope(Acts::ExtentEnvelope{{
456 .z = {1_mm, 1_mm},
457 .r = {2_mm, 2_mm},
458 }});
459 };
460
461 ATH_MSG_VERBOSE("Add inner pixel layer"
462 << key << " / " << mergedLayers.size()
463 << " at z = " << pl.protoLayer.medium(AxisZ));
464 ATH_MSG_VERBOSE("Adding material for layer " << layerName);
465 ec.addMaterial(layerName + "_Material", [&](auto& lmat) {
466 lmat.configureFace(NegativeDisc,
467 AxisSpec::DeferredEquidistant(10, AxisR),
468 AxisSpec::DeferredEquidistant(40, AxisPhi));
469 lmat.configureFace(PositiveDisc,
470 AxisSpec::DeferredEquidistant(10, AxisR),
471 AxisSpec::DeferredEquidistant(40, AxisPhi));
472 addLayer(lmat);
473 });
474 }
475 }
476 });
477
478 // Outer pixel: 3 outer barrel layers + outer endcaps
479 auto& outerPixel = node.addCylinderContainer("OuterPixel", AxisR);
480 outerPixel.setAttachmentStrategy(AttachmentStrategy::Gap);
481 outerPixel.setResizeStrategy(ResizeStrategy::Gap);
482
483 outerPixel.addMaterial("OuterPixelMaterial", [&](auto& opmat) {
484 opmat.configureFace(OuterCylinder,
485 AxisSpec::DeferredEquidistant(20, AxisRPhi),
486 AxisSpec::DeferredEquidistant(20, AxisZ));
487 opmat.configureFace(InnerCylinder,
488 AxisSpec::DeferredEquidistant(20, AxisRPhi),
489 AxisSpec::DeferredEquidistant(20, AxisZ));
490
491 auto& outerPixelContainer = opmat.addCylinderContainer("OuterPixel", AxisZ);
492
493 auto& barrelGeoId = outerPixelContainer.withGeometryIdentifier();
494 barrelGeoId.setAllVolumeIdsTo(s_outerPixelVolumeId).incrementLayerIds(1);
495
496 auto& brl_mat =
497 barrelGeoId.addMaterial("OuterPixel_Material", [&](auto& bmat) {
498 bmat.configureFace(NegativeDisc,
499 AxisSpec::DeferredEquidistant(10, AxisR),
500 AxisSpec::DeferredEquidistant(10, AxisPhi));
501 bmat.configureFace(PositiveDisc,
502 AxisSpec::DeferredEquidistant(10, AxisR),
503 AxisSpec::DeferredEquidistant(10, AxisPhi));
504 });
505 auto& barrel = brl_mat.addCylinderContainer("OuterPixel_Brl", AxisR);
506
507 barrel.setAttachmentStrategy(AttachmentStrategy::Gap);
508 barrel.setResizeStrategy(ResizeStrategy::Gap);
509
510 std::map<int, std::vector<std::shared_ptr<Acts::Surface>>> layers{};
511
512 for (auto& element : elements) {
513 IdentityHelper id = element->identityHelper();
514 if (id.bec() != 0) {
515 continue;
516 }
517
518 if (id.layer_disk() <= 1) {
519 continue;
520 }
521
522 int elementLayer = id.layer_disk();
523 layers[elementLayer].push_back(element->surface().getSharedPtr());
524 }
525
526 ATH_MSG_DEBUG("Adding " << layers.size() << " layers to OuterPixel barrel");
527
528 for (const auto& [ilayer, surfaces] : layers) {
529 ATH_MSG_DEBUG("- Layer " << ilayer << " has " << surfaces.size()
530 << " surfaces");
531
532 barrel.addMaterial(
533 std::format("OuterPixel_Brl_{}_Material", ilayer), [&](auto& lmat) {
534 lmat.configureFace(OuterCylinder,
535 AxisSpec::DeferredEquidistant(40, AxisRPhi),
536 AxisSpec::DeferredEquidistant(20, AxisZ));
537
538 auto& layer =
539 lmat.addLayer("OuterPixel_Brl_" + std::to_string(ilayer));
540
541 layer.setNavigationPolicyFactory(
542 Acts::NavigationPolicyFactory{}
543 .add<Acts::SurfaceArrayNavigationPolicy>(
544 Acts::SurfaceArrayNavigationPolicy::Config{
545 .layerType = Cylinder,
546 .bins = {30, 10}})
547 .add<Acts::TryAllNavigationPolicy>(
548 Acts::TryAllNavigationPolicy::Config{.sensitives =
549 false})
550 .asUniquePtr());
551
552 layer.setSurfaces(surfaces);
553 layer.setEnvelope(Acts::ExtentEnvelope{{
554 .z = {5_mm, 5_mm},
555 .r = {2_mm, 2_mm},
556 }});
557 });
558 }
559
560 constexpr static auto addEndcapLayer = [](auto& parent, const auto& name,
561 const auto& surfaces) {
562 parent.addLayer(name, [&surfaces](auto& layer) {
563 layer.setNavigationPolicyFactory(
564 Acts::NavigationPolicyFactory{}
565 .add<Acts::SurfaceArrayNavigationPolicy>(
566 Acts::SurfaceArrayNavigationPolicy::Config{
567 .layerType = Disc, .bins = {30, 30}})
568 .add<Acts::TryAllNavigationPolicy>(
569 Acts::TryAllNavigationPolicy::Config{.sensitives = false})
570 .asUniquePtr());
571
572 layer.setSurfaces(surfaces);
573 });
574 };
575
576 for (int bec : {-2, 2}) {
577 const std::string s = bec > 0 ? "p" : "n";
578
579 auto& ec_outer_geoId = outerPixelContainer.withGeometryIdentifier();
580 ec_outer_geoId
581 .setAllVolumeIdsTo(s_outerPixelVolumeId + std::floor(bec / 2))
582 .incrementLayerIds(1);
583
584 auto& ec_outer =
585 ec_outer_geoId.addCylinderContainer("OuterPixel_" + s + "EC", AxisR);
586
587 // Three groups of disks stacked in R
588 std::array diskGroups{std::pair{3, 4}, std::pair{6, 5}, std::pair{7, 8}};
589
590 for (size_t idx = 0; idx < diskGroups.size(); ++idx) {
591 auto [disk1, disk2] = diskGroups[idx];
592
593 Acts::MaterialDesignatorBlueprintNode* material = nullptr;
594 if (idx < (diskGroups.size() - 1)) {
595 material = &ec_outer.addMaterial(
596 "OuterPixel_" + s + "EC_" + std::to_string(idx) + "_Material",
597 [&](auto& mat) {
598 mat.configureFace(OuterCylinder,
599 AxisSpec::DeferredEquidistant(20, AxisRPhi),
600 AxisSpec::DeferredEquidistant(20, AxisZ));
601 });
602 }
603
604 auto& ec_stack =
605 material
606 ? material->addCylinderContainer(
607 "OuterPixel_" + s + "EC_" + std::to_string(idx), AxisZ)
608 : ec_outer.addCylinderContainer(
609 "OuterPixel_" + s + "EC_" + std::to_string(idx), AxisZ);
610
611 ec_stack.setAttachmentStrategy(AttachmentStrategy::Gap);
612 ec_stack.setResizeStrategy(ResizeStrategy::Gap);
613
614 std::map<std::tuple<int, int>,
615 std::vector<std::shared_ptr<Acts::Surface>>>
616 eta_rings;
617
618 for (auto& element : elements) {
619 IdentityHelper id = element->identityHelper();
620 if (id.bec() != bec ||
621 (id.layer_disk() != disk1 && id.layer_disk() != disk2)) {
622 continue;
623 }
624 std::tuple<int, int> key{id.layer_disk(), id.eta_module()};
625 eta_rings[key].push_back(element->surface().getSharedPtr());
626 }
627
628 ATH_MSG_DEBUG("Found " << eta_rings.size() << " eta rings in group "
629 << idx);
630
631 std::vector<std::vector<std::shared_ptr<Acts::Surface>>> sorted_rings;
632 sorted_rings.reserve(eta_rings.size());
633 for (const auto& [key, surfaces] : eta_rings) {
634 sorted_rings.push_back(surfaces);
635 }
636
637 std::ranges::sort(sorted_rings, [&gctx](const auto& a, const auto& b) {
638 Acts::ProtoLayer pl_a(gctx, makeConstPtrVector(a));
639 Acts::ProtoLayer pl_b(gctx, makeConstPtrVector(b));
640 return std::abs(pl_a.min(AxisZ)) < std::abs(pl_b.min(AxisZ));
641 });
642
643 for (size_t i = 0; i < sorted_rings.size(); ++i) {
644 const auto& surfaces = sorted_rings[i];
645 auto layerName = "OuterPixel_" + s + "EC_" + std::to_string(idx) +
646 "_" + std::to_string(i);
647
648 ec_stack.addMaterial(layerName + "_Material", [&](auto& mat) {
649 mat.configureFace(PositiveDisc,
650 AxisSpec::DeferredEquidistant(10, AxisR),
651 AxisSpec::DeferredEquidistant(40, AxisPhi));
652 mat.configureFace(NegativeDisc,
653 AxisSpec::DeferredEquidistant(10, AxisR),
654 AxisSpec::DeferredEquidistant(40, AxisPhi));
655 addEndcapLayer(mat, layerName, surfaces);
656 });
657 }
658 }
659 }
660 });
661}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
static Double_t a
const InDetDD::SiDetectorManager * m_itkPixelMgr
std::shared_ptr< ActsElementVector > m_elementStore
Gaudi::Property< bool > m_doEndcapLayerMerging
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
constexpr std::size_t s_outerPixelVolumeId
constexpr std::size_t s_innerPixelVolumeId
const std::string & layerName(LayerIndex index)
convert LayerIndex into a string
@ layer
Definition HitInfo.h:79

◆ buildItkStripBlueprintNode()

void ActsTrk::ItkBlueprintNodeBuilder::buildItkStripBlueprintNode ( const Acts::GeometryContext & gctx,
Acts::BlueprintNode & node )
private

Definition at line 663 of file ItkBlueprintNodeBuilder.cxx.

665 {
666
667 // Get ITkStrip parameters from detector manager
668 if (!m_itkStripMgr) {
669 ATH_MSG_ERROR("ITkStrip manager not available");
670 throw std::runtime_error("ITkStrip manager not available");
671 }
672
673 ATH_MSG_DEBUG("Detector manager has "
674 << m_itkStripMgr->getDetectorElementCollection()->size()
675 << " elements");
676
677 std::vector<std::shared_ptr<ActsDetectorElement>> elements;
678
680 for (const auto* element : *m_itkStripMgr->getDetectorElementCollection()) {
681 const InDetDD::SiDetectorElement* siDetElement =
682 dynamic_cast<const InDetDD::SiDetectorElement*>(element);
683 if (siDetElement == nullptr) {
684 ATH_MSG_ERROR("Detector element was nullptr");
685 throw std::runtime_error{"Corrupt detector element collection"};
686 }
687 elements.push_back(std::make_shared<ActsDetectorElement>(*siDetElement));
688 }
689 ATH_MSG_VERBOSE("Retrieved " << elements.size() << " elements");
690
691 // Copy to service level store to extend lifetime
692 m_elementStore->vector().insert(m_elementStore->vector().end(),
693 elements.begin(), elements.end());
694
695 auto& strip = node.addCylinderContainer("Strip", AxisR);
696 strip.setAttachmentStrategy(AttachmentStrategy::Gap);
697 strip.setResizeStrategy(ResizeStrategy::Gap);
698
699 strip.addMaterial("StripMaterial", [&](auto& mat) {
700 mat.configureFace(OuterCylinder,
701 AxisSpec::DeferredEquidistant(20, AxisRPhi),
702 AxisSpec::DeferredEquidistant(20, AxisZ));
703 mat.configureFace(InnerCylinder,
704 AxisSpec::DeferredEquidistant(20, AxisRPhi),
705 AxisSpec::DeferredEquidistant(20, AxisZ));
706
707 auto& stripContainer = mat.addCylinderContainer("Strip", AxisZ);
708
709 // Add barrel container
710 stripContainer.withGeometryIdentifier([this, &elements](auto& geoId) {
711 geoId.setAllVolumeIdsTo(s_stripVolumeId).incrementLayerIds(1);
712
713 auto& brl_mat =
714 geoId.addMaterial("Strip_Brl_Material", [&](auto& material) {
715 material.configureFace(NegativeDisc,
716 AxisSpec::DeferredEquidistant(10, AxisR),
717 AxisSpec::DeferredEquidistant(10, AxisPhi));
718 material.configureFace(PositiveDisc,
719 AxisSpec::DeferredEquidistant(10, AxisR),
720 AxisSpec::DeferredEquidistant(10, AxisPhi));
721 });
722 brl_mat.addCylinderContainer(
723 "Strip_Brl", AxisR, [this, &elements](auto& barrel) {
724 barrel.setAttachmentStrategy(AttachmentStrategy::Gap);
725 barrel.setResizeStrategy(ResizeStrategy::Gap);
726
727 std::map<int, std::vector<std::shared_ptr<Acts::Surface>>> layers{};
728
729 for (auto& element : elements) {
730 IdentityHelper id = element->identityHelper();
731 if (id.bec() != 0) {
732 continue;
733 }
734
735 int elementLayer = id.layer_disk();
736 layers[elementLayer].push_back(element->surface().getSharedPtr());
737 }
738
739 ATH_MSG_DEBUG("Adding " << layers.size()
740 << " layers to Strip barrel");
741
742 for (const auto& [ilayer, surfaces] : layers) {
743 ATH_MSG_DEBUG("- Layer " << ilayer << " has " << surfaces.size()
744 << " surfaces");
745 addStripBarrelLayer(barrel, ilayer, surfaces);
746 }
747 });
748 });
749
750 // Add endcap containers
751 for (int bec : {-2, 2}) {
752 const std::string s = bec > 0 ? "p" : "n";
753
754 std::map<int, std::vector<std::shared_ptr<Acts::Surface>>> layers{};
755
756 for (auto& element : elements) {
757 IdentityHelper id = element->identityHelper();
758 if (id.bec() * bec <= 0) {
759 continue;
760 }
761
762 layers[id.layer_disk()].push_back(element->surface().getSharedPtr());
763 }
764
765 ATH_MSG_DEBUG("Found " << layers.size() << " layers in Strip " << s
766 << "EC");
767
768 std::vector<std::vector<std::shared_ptr<Acts::Surface>>> sorted_layers;
769 sorted_layers.reserve(layers.size());
770 for (const auto& [key, surfaces] : layers) {
771 sorted_layers.push_back(surfaces);
772 }
773
774 std::sort(sorted_layers.begin(), sorted_layers.end(),
775 [&gctx](const auto& a, const auto& b) {
776 Acts::ProtoLayer pl_a(gctx, makeConstPtrVector(a));
777 Acts::ProtoLayer pl_b(gctx, makeConstPtrVector(b));
778 return std::abs(pl_a.min(AxisZ)) < std::abs(pl_b.min(AxisZ));
779 });
780
781 stripContainer.withGeometryIdentifier([&sorted_layers, bec,
782 &s](auto& geoId) {
783 geoId.setAllVolumeIdsTo(s_stripVolumeId + std::floor(bec / 2))
784 .incrementLayerIds(1);
785
786 geoId.addCylinderContainer(
787 "Strip_" + s + "EC", AxisZ, [&sorted_layers, &s](auto& ec) {
788 ec.setAttachmentStrategy(AttachmentStrategy::Gap);
789 ec.setResizeStrategy(ResizeStrategy::Gap);
790
791 for (size_t i = 0; i < sorted_layers.size(); ++i) {
792 const auto& surfaces = sorted_layers[i];
793 auto layerName = "Strip_" + s + "EC_" + std::to_string(i);
794 addStripEndcapLayer(ec, layerName, surfaces);
795 }
796 });
797 });
798 };
799 });
800
801 // Explicit spacer volume beyond the strip detector's natural outer radius.
802 // Without it, the outer cylinder carrying the strip container material
803 // coincides with the ITk node boundary, causing volume merging issues.
804 std::vector<std::shared_ptr<Acts::Surface>> allStripSurfaces;
805 allStripSurfaces.reserve(elements.size());
806 for (auto& element : elements) {
807 allStripSurfaces.push_back(element->surface().getSharedPtr());
808 }
809 Acts::ProtoLayer stripExtent(gctx, makeConstPtrVector(allStripSurfaces));
810
811 constexpr double spacerClearance = 5_mm;
812 constexpr double spacerThickness = 5_mm;
813 double spacerRmin = stripExtent.max(AxisR) + spacerClearance;
814 double spacerHalfZ = std::max(std::abs(stripExtent.min(AxisZ)),
815 std::abs(stripExtent.max(AxisZ))) +
816 spacerClearance;
817
818 strip.addStaticVolume(
819 Acts::Transform3::Identity(),
820 std::make_shared<Acts::CylinderVolumeBounds>(
821 spacerRmin, spacerRmin + spacerThickness, spacerHalfZ),
822 "Strip_OuterSpacer");
823}
const InDetDD::SiDetectorManager * m_itkStripMgr
constexpr std::size_t s_stripVolumeId
Volume Ids used within the ITk.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.

◆ initialize()

StatusCode ActsTrk::ItkBlueprintNodeBuilder::initialize ( )
override

Definition at line 193 of file ItkBlueprintNodeBuilder.cxx.

193 {
194 // Retrieve the detector managers from the detector store for enabled systems
195 if (m_buildPixel) {
196 ATH_CHECK(detStore()->retrieve(m_itkPixelMgr, "ITkPixel"));
197 }
198 if (m_buildStrip) {
199 ATH_CHECK(detStore()->retrieve(m_itkStripMgr, "ITkStrip"));
200 }
201 m_elementStore = std::make_shared<ActsElementVector>();
202 return StatusCode::SUCCESS;
203}
#define ATH_CHECK
Evaluate an expression and check for errors.

Member Data Documentation

◆ m_buildPixel

Gaudi::Property<bool> ActsTrk::ItkBlueprintNodeBuilder::m_buildPixel {this, "buildPixel", true}
private

Definition at line 41 of file ItkBlueprintNodeBuilder.h.

41{this, "buildPixel", true};

◆ m_buildStrip

Gaudi::Property<bool> ActsTrk::ItkBlueprintNodeBuilder::m_buildStrip {this, "buildStrip", true}
private

Definition at line 42 of file ItkBlueprintNodeBuilder.h.

42{this, "buildStrip", true};

◆ m_doEndcapLayerMerging

Gaudi::Property<bool> ActsTrk::ItkBlueprintNodeBuilder::m_doEndcapLayerMerging
private
Initial value:
{this, "doEndcapLayerMerging",
true}

Definition at line 39 of file ItkBlueprintNodeBuilder.h.

39 {this, "doEndcapLayerMerging",
40 true};

◆ m_elementStore

std::shared_ptr<ActsElementVector> ActsTrk::ItkBlueprintNodeBuilder::m_elementStore {nullptr}
private

Definition at line 37 of file ItkBlueprintNodeBuilder.h.

37{nullptr};

◆ m_itkPixelMgr

const InDetDD::SiDetectorManager* ActsTrk::ItkBlueprintNodeBuilder::m_itkPixelMgr {nullptr}
private

Definition at line 35 of file ItkBlueprintNodeBuilder.h.

35{nullptr};

◆ m_itkStripMgr

const InDetDD::SiDetectorManager* ActsTrk::ItkBlueprintNodeBuilder::m_itkStripMgr {nullptr}
private

Definition at line 36 of file ItkBlueprintNodeBuilder.h.

36{nullptr};

The documentation for this class was generated from the following files: