274 {
275
276
279 throw std::runtime_error("ITkPixel manager not available");
280 }
281
284 << " elements");
285
286 std::vector<std::shared_ptr<ActsDetectorElement>> elements;
287
289 for (
const auto* element : *
m_itkPixelMgr->getDetectorElementCollection()) {
290 const InDetDD::SiDetectorElement* siDetElement =
291 dynamic_cast<const InDetDD::SiDetectorElement*>(element);
292 if (siDetElement == nullptr) {
294 throw std::runtime_error{"Corrupt detector element collection"};
295 }
296 elements.push_back(std::make_shared<ActsDetectorElement>(*siDetElement));
297 }
299
300
302 elements.begin(), elements.end());
303
304
305 auto& innerPixel = node.addCylinderContainer("InnerPixel", AxisR);
306 innerPixel.setAttachmentStrategy(AttachmentStrategy::Gap);
307
308
309
310
311
312 innerPixel.setResizeStrategies(ResizeStrategy::Expand, ResizeStrategy::Gap);
313
314 innerPixel.addMaterial("InnerPixelMaterial", [&](auto& mat) {
315 mat.configureFace(OuterCylinder,
316 AxisSpec::DeferredEquidistant(50, AxisRPhi),
317 AxisSpec::DeferredEquidistant(100, AxisZ));
318
319 auto& innerPixelContainer =
mat.addCylinderContainer(
"InnerPixel", AxisZ);
320
321
322 auto& barrelGeoId = innerPixelContainer.withGeometryIdentifier();
324 .incrementLayerIds(1)
325 .sortBy([](
auto&
a,
auto& b) {
326 auto& boundsA =
327 dynamic_cast<const Acts::CylinderVolumeBounds&
>(
a.volumeBounds());
328 auto& boundsB =
329 dynamic_cast<const Acts::CylinderVolumeBounds&
>(
b.volumeBounds());
330
331 using enum Acts::CylinderVolumeBounds::BoundValues;
332 double aMidR = (boundsA.get(eMinR) + boundsA.get(eMaxR)) / 2.0;
333 double bMidR = (boundsB.get(eMinR) + boundsB.get(eMaxR)) / 2.0;
334
335 return aMidR < bMidR;
336 });
337
338 auto& brl_mat =
339 barrelGeoId.addMaterial("InnerPixel_Material", [&](auto& material) {
340 material.configureFace(NegativeDisc,
341 AxisSpec::DeferredEquidistant(50, AxisR),
342 AxisSpec::DeferredEquidistant(50, AxisPhi));
343 material.configureFace(PositiveDisc,
344 AxisSpec::DeferredEquidistant(50, AxisR),
345 AxisSpec::DeferredEquidistant(50, AxisPhi));
346 });
347 auto&
barrel = brl_mat.addCylinderContainer(
"InnerPixel_Brl", AxisR);
348
349
350
351
352
353 barrel.setAttachmentStrategy(AttachmentStrategy::Second);
354
355
356
357
358
359
360
361
362
363 barrel.setResizeStrategies(ResizeStrategy::Expand, ResizeStrategy::Expand);
364
365 std::map<int, std::vector<std::shared_ptr<Acts::Surface>>>
layers{};
366
367 for (auto& element : elements) {
368 IdentityHelper id = element->identityHelper();
370 continue;
371 }
372
373 if (id.layer_disk() >= 2) {
374 continue;
375 }
376
377 int elementLayer = id.layer_disk();
378 layers[elementLayer].push_back(element->surface().getSharedPtr());
379 }
380
382
383 const int outermostBrlLayer =
layers.rbegin()->first;
384 for (const auto& [ilayer, surfaces] : layers) {
385 ATH_MSG_DEBUG(
"- Layer " << ilayer <<
" has " << surfaces.size()
386 << " surfaces");
387
388 auto configureLayer = [&](auto& node) {
389 auto&
layer = node.addLayer(std::format(
"InnerPixel_Brl_{}", ilayer));
390 layer.setNavigationPolicyFactory(
391 Acts::NavigationPolicyFactory{}
392 .add<Acts::SurfaceArrayNavigationPolicy>(
393 Acts::SurfaceArrayNavigationPolicy::Config{
395 .bins = {0, 0}, .numberOfBinsFactor = 5.0})
396 .add<Acts::CylinderNavigationPolicy>()
397 .asUniquePtr());
398 layer.setSurfaces(surfaces);
399 layer.setEnvelope(Acts::ExtentEnvelope{{
400 .z = {5_mm, 5_mm},
401 .r = {2_mm, 2_mm},
402 }});
403 };
404
405
406
407
408 if (ilayer != outermostBrlLayer) {
410 std::format("InnerPixel_Brl_{}_Material", ilayer),
411 [&](auto& lmat) {
412 lmat.configureFace(OuterCylinder,
413 AxisSpec::DeferredEquidistant(50, AxisRPhi),
414 AxisSpec::DeferredEquidistant(100, AxisZ));
415 configureLayer(lmat);
416 });
417 } else {
419 }
420 }
421
422
423 for (int bec : {-2, 2}) {
424 std::string
s =
bec > 0 ?
"p" :
"n";
425 auto& ecGeoId = innerPixelContainer.withGeometryIdentifier();
427 .incrementLayerIds(1);
428 auto& ec = ecGeoId.addCylinderContainer("InnerPixel_" + s + "EC", AxisZ);
429
430
431
432
433 ec.setAttachmentStrategy(bec > 0 ? AttachmentStrategy::Second
434 : AttachmentStrategy::First);
435
436
437
438
439
440
441 ec.setResizeStrategies(
442 bec > 0 ? ResizeStrategy::Expand : ResizeStrategy::Gap,
443 bec > 0 ? ResizeStrategy::Gap : ResizeStrategy::Expand);
444
445 std::map<std::tuple<int, int, int>,
446 std::vector<std::shared_ptr<Acts::Surface>>>
447 initialLayers{};
448
449 for (auto& element : elements) {
450 IdentityHelper id = element->identityHelper();
451 if (
id.
bec() * bec <= 0) {
452 continue;
453 }
454
455 if (id.layer_disk() >= 3) {
456 continue;
457 }
458
459 std::tuple<int, int, int>
key{
id.bec(),
id.layer_disk(),
460 id.eta_module()};
461 initialLayers[
key].push_back(element->surface().getSharedPtr());
462 }
463
465 << " initial layers to InnerPixel " << s << "EC");
466
467 std::vector<LayerData> protoLayers;
468 protoLayers.reserve(initialLayers.size());
469
470 for (const auto& [key, surfaces] : initialLayers) {
471 auto&
layer = protoLayers.emplace_back(gctx, surfaces);
472 layer.protoLayer.envelope[AxisR] = {2_mm, 2_mm};
473 layer.protoLayer.envelope[AxisZ] = {1_mm, 1_mm};
474 }
475
476 std::ranges::sort(protoLayers,
477 [](
const LayerData&
a,
const LayerData& b) {
478 return std::abs(
a.protoLayer.medium(AxisZ)) <
479 std::abs(
b.protoLayer.medium(AxisZ));
480 });
481
482 ATH_MSG_DEBUG(
"Found " << protoLayers.size() <<
" initial layers");
483
484 std::vector<LayerData> mergedLayers;
486 mergedLayers = mergeLayers(gctx, std::move(protoLayers));
487 } else {
488 mergedLayers = std::move(protoLayers);
489 }
490
491 ATH_MSG_DEBUG(
"After merging: " << mergedLayers.size() <<
" layers");
492
493 for (const auto [key, pl] : Acts::enumerate(mergedLayers)) {
494 ATH_MSG_DEBUG(
"- Layer " << key <<
" has " << pl.surfaces.size()
495 << " surfaces");
496
497 pl.protoLayer.medium(AxisZ);
498 auto layerName = std::format(
"InnerPixel_{}EC_{}", key, s);
499
502
503 layer.setNavigationPolicyFactory(
504 Acts::NavigationPolicyFactory{}
505 .add<Acts::SurfaceArrayNavigationPolicy>(
506 Acts::SurfaceArrayNavigationPolicy::Config{
508 .bins = {0, 0}, .numberOfBinsFactor = 5.0})
509 .add<Acts::CylinderNavigationPolicy>()
510 .asUniquePtr());
511
512 layer.setSurfaces(pl.surfaces);
513 layer.setEnvelope(Acts::ExtentEnvelope{{
514 .z = {1_mm, 1_mm},
515 .r = {2_mm, 2_mm},
516 }});
517 };
518
520 << key << " / " << mergedLayers.size()
521 << " at z = " << pl.protoLayer.medium(AxisZ));
523
524
525
526
527
528
529 const auto outwardDisc = (
bec > 0) ? PositiveDisc : NegativeDisc;
530 ec.addMaterial(layerName + "_Material", [&](auto& lmat) {
531 lmat.configureFace(outwardDisc,
532 AxisSpec::DeferredEquidistant(50, AxisR),
533 AxisSpec::DeferredEquidistant(50, AxisPhi));
534 addLayer(lmat);
535 });
536 }
537 }
538 });
539
540
541 auto& outerPixel = node.addCylinderContainer("OuterPixel", AxisR);
542 outerPixel.setAttachmentStrategy(AttachmentStrategy::Gap);
543
544
545
546
547
548 outerPixel.setResizeStrategies(ResizeStrategy::Expand, ResizeStrategy::Gap);
549
550 outerPixel.addMaterial("OuterPixelMaterial", [&](auto& opmat) {
551 opmat.configureFace(OuterCylinder,
552 AxisSpec::DeferredEquidistant(50, AxisRPhi),
553 AxisSpec::DeferredEquidistant(100, AxisZ));
554
555 auto& outerPixelContainer = opmat.addCylinderContainer("OuterPixel", AxisZ);
556
557 auto& barrelGeoId = outerPixelContainer.withGeometryIdentifier();
559
560 auto& brl_mat =
561 barrelGeoId.addMaterial("OuterPixel_Material", [&](auto& bmat) {
562 bmat.configureFace(NegativeDisc,
563 AxisSpec::DeferredEquidistant(50, AxisR),
564 AxisSpec::DeferredEquidistant(50, AxisPhi));
565 bmat.configureFace(PositiveDisc,
566 AxisSpec::DeferredEquidistant(50, AxisR),
567 AxisSpec::DeferredEquidistant(50, AxisPhi));
568 });
569 auto&
barrel = brl_mat.addCylinderContainer(
"OuterPixel_Brl", AxisR);
570
571
572
573
574 barrel.setAttachmentStrategy(AttachmentStrategy::Second);
575
576
577
578
579
580
581
582 barrel.setResizeStrategies(ResizeStrategy::Expand, ResizeStrategy::Expand);
583
584 std::map<int, std::vector<std::shared_ptr<Acts::Surface>>>
layers{};
585
586 for (auto& element : elements) {
587 IdentityHelper id = element->identityHelper();
589 continue;
590 }
591
592 if (id.layer_disk() <= 1) {
593 continue;
594 }
595
596 int elementLayer = id.layer_disk();
597 layers[elementLayer].push_back(element->surface().getSharedPtr());
598 }
599
601
602 const int outermostBrlLayer =
layers.rbegin()->first;
603 for (const auto& [ilayer, surfaces] : layers) {
604 ATH_MSG_DEBUG(
"- Layer " << ilayer <<
" has " << surfaces.size()
605 << " surfaces");
606
607 auto configureLayer = [&](auto& node) {
608 auto&
layer = node.addLayer(
"OuterPixel_Brl_" + std::to_string(ilayer));
609 layer.setNavigationPolicyFactory(
610 Acts::NavigationPolicyFactory{}
611 .add<Acts::SurfaceArrayNavigationPolicy>(
612 Acts::SurfaceArrayNavigationPolicy::Config{
614 .bins = {0, 0}, .numberOfBinsFactor = 5.0})
615 .add<Acts::CylinderNavigationPolicy>()
616 .asUniquePtr());
617 layer.setSurfaces(surfaces);
618 layer.setEnvelope(Acts::ExtentEnvelope{{
619 .z = {5_mm, 5_mm},
620 .r = {2_mm, 2_mm},
621 }});
622 };
623
624
625
626
627 if (ilayer != outermostBrlLayer) {
629 std::format("OuterPixel_Brl_{}_Material", ilayer),
630 [&](auto& lmat) {
631 lmat.configureFace(OuterCylinder,
632 AxisSpec::DeferredEquidistant(50, AxisRPhi),
633 AxisSpec::DeferredEquidistant(100, AxisZ));
634 configureLayer(lmat);
635 });
636 } else {
638 }
639 }
640
641 constexpr static auto addEndcapLayer = [](
auto&
parent,
const auto&
name,
642 const auto& surfaces) {
643 parent.addLayer(name, [&surfaces](
auto& layer) {
644 layer.setNavigationPolicyFactory(
645 Acts::NavigationPolicyFactory{}
646 .add<Acts::SurfaceArrayNavigationPolicy>(
647 Acts::SurfaceArrayNavigationPolicy::Config{
648 .layerType =
Disc, .bins = {0, 0}, .numberOfBinsFactor = 5.0})
649 .add<Acts::CylinderNavigationPolicy>()
650 .asUniquePtr());
651
652 layer.setSurfaces(surfaces);
653 });
654 };
655
656 for (int bec : {-2, 2}) {
657 const std::string
s =
bec > 0 ?
"p" :
"n";
658
659 auto& ec_outer_geoId = outerPixelContainer.withGeometryIdentifier();
660 ec_outer_geoId
662 .incrementLayerIds(1);
663
664 auto& ec_outer =
665 ec_outer_geoId.addCylinderContainer("OuterPixel_" + s + "EC", AxisR);
666
667
668 std::array diskGroups{std::pair{3, 4}, std::pair{6, 5}, std::pair{7, 8}};
669
670 for (
size_t idx = 0;
idx < diskGroups.size(); ++
idx) {
671 auto [disk1, disk2] = diskGroups[
idx];
672
673 Acts::MaterialDesignatorBlueprintNode* material = nullptr;
674 if (idx < (diskGroups.size() - 1)) {
675 material = &ec_outer.addMaterial(
676 "OuterPixel_" + s + "EC_" + std::to_string(idx) + "_Material",
677 [&](auto& mat) {
678 mat.configureFace(OuterCylinder,
679 AxisSpec::DeferredEquidistant(50, AxisRPhi),
680 AxisSpec::DeferredEquidistant(100, AxisZ));
681 });
682 }
683
684 auto& ec_stack =
685 material
686 ? material->addCylinderContainer(
687 "OuterPixel_" + s + "EC_" + std::to_string(idx), AxisZ)
688 : ec_outer.addCylinderContainer(
689 "OuterPixel_" + s + "EC_" + std::to_string(idx), AxisZ);
690
691
692
693
694 ec_stack.setAttachmentStrategy(bec > 0 ? AttachmentStrategy::Second
695 : AttachmentStrategy::First);
696
697
698
699
700 ec_stack.setResizeStrategies(
701 bec > 0 ? ResizeStrategy::Expand : ResizeStrategy::Gap,
702 bec > 0 ? ResizeStrategy::Gap : ResizeStrategy::Expand);
703
704 std::map<std::tuple<int, int>,
705 std::vector<std::shared_ptr<Acts::Surface>>>
706 eta_rings;
707
708 for (auto& element : elements) {
709 IdentityHelper id = element->identityHelper();
710 if (
id.
bec() != bec ||
711 (id.layer_disk() != disk1 && id.layer_disk() != disk2)) {
712 continue;
713 }
714 std::tuple<int, int>
key{
id.layer_disk(),
id.eta_module()};
715 eta_rings[
key].push_back(element->surface().getSharedPtr());
716 }
717
718 ATH_MSG_DEBUG(
"Found " << eta_rings.size() <<
" eta rings in group "
719 << idx);
720
721 std::vector<std::vector<std::shared_ptr<Acts::Surface>>> sorted_rings;
722 sorted_rings.reserve(eta_rings.size());
723 for (const auto& [key, surfaces] : eta_rings) {
724 sorted_rings.push_back(surfaces);
725 }
726
727 std::ranges::sort(sorted_rings, [&gctx](
const auto&
a,
const auto& b) {
728 Acts::ProtoLayer pl_a(gctx, makeConstPtrVector(
a));
729 Acts::ProtoLayer pl_b(gctx, makeConstPtrVector(b));
730 return std::abs(pl_a.min(AxisZ)) < std::abs(pl_b.min(AxisZ));
731 });
732
733 for (
size_t i = 0;
i < sorted_rings.size(); ++
i) {
734 const auto& surfaces = sorted_rings[
i];
735 auto layerName =
"OuterPixel_" +
s +
"EC_" + std::to_string(idx) +
736 "_" + std::to_string(i);
737
738 const auto outwardDisc = (
bec > 0) ? PositiveDisc : NegativeDisc;
739 ec_stack.addMaterial(layerName + "_Material", [&](auto& mat) {
740 mat.configureFace(outwardDisc,
741 AxisSpec::DeferredEquidistant(50, AxisR),
742 AxisSpec::DeferredEquidistant(50, AxisPhi));
743 addEndcapLayer(mat, layerName, surfaces);
744 });
745 }
746 }
747 }
748 });
749}
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_VERBOSE(x,...)
const InDetDD::SiDetectorManager * m_itkPixelMgr
std::shared_ptr< ActsElementVector > m_elementStore
Gaudi::Property< bool > m_doEndcapLayerMerging
DataModel_detail::const_iterator< DataVector > const_iterator
constexpr std::size_t s_outerPixelVolumeId
constexpr std::size_t s_innerPixelVolumeId
const std::string & layerName(LayerIndex index)
convert LayerIndex into a string