250 throw std::runtime_error(
"ITkPixel manager not available");
257 std::vector<std::shared_ptr<ActsDetectorElement>> elements;
260 for (
const auto* element :
264 if (siDetElement ==
nullptr) {
266 throw std::runtime_error{
"Corrupt detector element collection"};
268 elements.push_back(std::make_shared<ActsDetectorElement>(*siDetElement));
274 elements.begin(), elements.end());
277 node.addMaterial(
"InnerPixelMaterial", [&](
auto&
mat) {
278 mat.configureFace(OuterCylinder, {AxisRPhi, Bound, 20}, {AxisZ, Bound, 20});
280 auto& innerPixelContainer =
mat.addCylinderContainer(
"InnerPixel", AxisZ);
283 auto& barrelGeoId = innerPixelContainer.withGeometryIdentifier();
284 barrelGeoId.setAllVolumeIdsTo(s_innerPixelVolumeId)
285 .incrementLayerIds(1)
286 .sortBy([](
auto&
a,
auto&
b) {
288 dynamic_cast<const Acts::CylinderVolumeBounds&
>(
a.volumeBounds());
290 dynamic_cast<const Acts::CylinderVolumeBounds&
>(
b.volumeBounds());
292 using enum Acts::CylinderVolumeBounds::BoundValues;
293 double aMidR = (boundsA.get(eMinR) + boundsA.get(eMaxR)) / 2.0;
294 double bMidR = (boundsB.get(eMinR) + boundsB.get(eMaxR)) / 2.0;
296 return aMidR < bMidR;
299 auto&
barrel = barrelGeoId.addCylinderContainer(
"InnerPixel_Brl", AxisR);
300 barrel.setAttachmentStrategy(AttachmentStrategy::Gap);
301 barrel.setResizeStrategy(ResizeStrategy::Gap);
303 std::map<int, std::vector<std::shared_ptr<Acts::Surface>>>
layers{};
305 for (
auto& element : elements) {
311 if (
id.layer_disk() >= 2) {
316 layers[elementLayer].push_back(element->surface().getSharedPtr());
321 for (
const auto& [ilayer, surfaces] :
layers) {
322 ATH_MSG_DEBUG(
"- Layer " << ilayer <<
" has " << surfaces.size()
326 std::format(
"InnerPixel_Brl_{}_Material", ilayer), [&](
auto& lmat) {
328 lmat.configureFace(OuterCylinder, {AxisRPhi, Bound, 40},
333 lmat.addLayer(
std::format(
"InnerPixel_Brl_{}", ilayer));
336 layer.setNavigationPolicyFactory(
337 Acts::NavigationPolicyFactory{}
338 .add<Acts::SurfaceArrayNavigationPolicy>(
339 Acts::SurfaceArrayNavigationPolicy::Config{
342 .add<Acts::TryAllNavigationPolicy>(
343 Acts::TryAllNavigationPolicy::Config{.sensitives =
347 layer.setSurfaces(surfaces);
348 layer.setEnvelope(Acts::ExtentEnvelope{{
356 for (
int bec : {-2, 2}) {
357 std::string
s =
bec > 0 ?
"p" :
"n";
358 auto& ecGeoId = innerPixelContainer.withGeometryIdentifier();
359 ecGeoId.setAllVolumeIdsTo(s_innerPixelVolumeId + std::floor(
bec / 2))
360 .incrementLayerIds(1);
361 auto& ec = ecGeoId.addCylinderContainer(
"InnerPixel_" +
s +
"EC", AxisZ);
362 ec.setAttachmentStrategy(AttachmentStrategy::Gap);
363 ec.setResizeStrategy(ResizeStrategy::Expand);
365 std::map<std::tuple<int, int, int>,
366 std::vector<std::shared_ptr<Acts::Surface>>>
369 for (
auto& element : elements) {
371 if (
id.
bec() *
bec <= 0) {
375 if (
id.layer_disk() >= 3) {
379 std::tuple<int, int, int>
key{
id.bec(),
id.layer_disk(),
381 initialLayers[
key].push_back(element->surface().getSharedPtr());
385 <<
" initial layers to InnerPixel " <<
s <<
"EC");
388 std::vector<LayerData> protoLayers;
389 protoLayers.reserve(initialLayers.size());
391 for (
const auto& [
key, surfaces] : initialLayers) {
392 auto&
layer = protoLayers.emplace_back(gctx, surfaces);
393 layer.protoLayer.envelope[AxisR] = {2_mm, 2_mm};
394 layer.protoLayer.envelope[AxisZ] = {1_mm, 1_mm};
398 std::ranges::sort(protoLayers,
399 [](
const LayerData&
a,
const LayerData&
b) {
400 return std::abs(
a.protoLayer.medium(AxisZ)) <
401 std::abs(
b.protoLayer.medium(AxisZ));
404 ATH_MSG_DEBUG(
"Found " << protoLayers.size() <<
" initial layers");
407 std::vector<LayerData> mergedLayers;
409 mergedLayers = mergeLayers(gctx, std::move(protoLayers));
411 mergedLayers = std::move(protoLayers);
414 ATH_MSG_DEBUG(
"After merging: " << mergedLayers.size() <<
" layers");
417 for (
const auto [
key, pl] : Acts::enumerate(mergedLayers)) {
421 pl.protoLayer.medium(AxisZ);
429 layer.setNavigationPolicyFactory(
430 Acts::NavigationPolicyFactory{}
431 .add<Acts::SurfaceArrayNavigationPolicy>(
432 Acts::SurfaceArrayNavigationPolicy::Config{
435 .add<Acts::TryAllNavigationPolicy>(
436 Acts::TryAllNavigationPolicy::Config{.sensitives =
false})
439 layer.setSurfaces(pl.surfaces);
440 layer.setEnvelope(Acts::ExtentEnvelope{{
447 <<
key <<
" / " << mergedLayers.size()
448 <<
" at z = " << pl.protoLayer.medium(AxisZ));
449 if (
key < mergedLayers.size() - 1) {
452 ec.addMaterial(layerName +
"_Material", [&](
auto& lmat) {
454 lmat.configureFace(
bec < 0 ? NegativeDisc : PositiveDisc,
455 {AxisR, Bound, 40}, {AxisPhi, Bound, 40});
466 node.addMaterial(
"OuterPixelMaterial", [&](
auto&
mat) {
467 mat.configureFace(OuterCylinder, {AxisRPhi, Bound, 20}, {AxisZ, Bound, 20});
469 auto& outerPixelContainer =
mat.addCylinderContainer(
"OuterPixel", AxisZ);
472 auto& barrelGeoId = outerPixelContainer.withGeometryIdentifier();
473 barrelGeoId.setAllVolumeIdsTo(s_outerPixelVolumeId).incrementLayerIds(1);
475 auto&
barrel = barrelGeoId.addCylinderContainer(
"OuterPixel_Brl", AxisR);
476 barrel.setAttachmentStrategy(AttachmentStrategy::Gap);
477 barrel.setResizeStrategy(ResizeStrategy::Gap);
479 std::map<int, std::vector<std::shared_ptr<Acts::Surface>>>
layers{};
481 for (
auto& element : elements) {
487 if (
id.layer_disk() <= 1) {
492 layers[elementLayer].push_back(element->surface().getSharedPtr());
497 for (
const auto& [ilayer, surfaces] :
layers) {
498 ATH_MSG_DEBUG(
"- Layer " << ilayer <<
" has " << surfaces.size()
502 std::format(
"OuterPixel_Brl_{}_Material", ilayer), [&](
auto& lmat) {
504 lmat.configureFace(OuterCylinder, {AxisRPhi, Bound, 40},
512 layer.setNavigationPolicyFactory(
513 Acts::NavigationPolicyFactory{}
514 .add<Acts::SurfaceArrayNavigationPolicy>(
515 Acts::SurfaceArrayNavigationPolicy::Config{
518 .add<Acts::TryAllNavigationPolicy>(
519 Acts::TryAllNavigationPolicy::Config{.sensitives =
523 layer.setSurfaces(surfaces);
524 layer.setEnvelope(Acts::ExtentEnvelope{{
531 constexpr
static auto addEndcapLayer = [](
auto&
parent,
const auto&
name,
532 const auto& surfaces) {
534 layer.setNavigationPolicyFactory(
535 Acts::NavigationPolicyFactory{}
536 .add<Acts::SurfaceArrayNavigationPolicy>(
537 Acts::SurfaceArrayNavigationPolicy::Config{
538 .layerType =
Disc, .bins = {30, 30}})
539 .add<Acts::TryAllNavigationPolicy>(
540 Acts::TryAllNavigationPolicy::Config{.sensitives =
false})
543 layer.setSurfaces(surfaces);
548 for (
int bec : {-2, 2}) {
549 const std::string
s =
bec > 0 ?
"p" :
"n";
553 auto& ec_outer_geoId = outerPixelContainer.withGeometryIdentifier();
555 .setAllVolumeIdsTo(s_outerPixelVolumeId + std::floor(
bec / 2))
556 .incrementLayerIds(1);
559 ec_outer_geoId.addCylinderContainer(
"OuterPixel_" +
s +
"EC", AxisR);
562 std::array diskGroups{std::pair{3, 4}, std::pair{6, 5}, std::pair{7, 8}};
564 for (
size_t idx = 0;
idx < diskGroups.size(); ++
idx) {
565 auto [disk1, disk2] = diskGroups[
idx];
567 auto& ec_stack = ec_outer.addCylinderContainer(
570 ec_stack.setAttachmentStrategy(AttachmentStrategy::Gap);
571 ec_stack.setResizeStrategy(ResizeStrategy::Expand);
574 std::map<std::tuple<int, int>,
575 std::vector<std::shared_ptr<Acts::Surface>>>
578 for (
auto& element : elements) {
581 (
id.layer_disk() != disk1 &&
id.layer_disk() != disk2)) {
584 std::tuple<int, int>
key{
id.layer_disk(),
id.eta_module()};
585 eta_rings[
key].push_back(element->surface().getSharedPtr());
588 ATH_MSG_DEBUG(
"Found " << eta_rings.size() <<
" eta rings in group "
592 std::vector<std::vector<std::shared_ptr<Acts::Surface>>> sorted_rings;
593 sorted_rings.reserve(eta_rings.size());
594 for (
const auto& [
key, surfaces] : eta_rings) {
595 sorted_rings.push_back(surfaces);
598 std::ranges::sort(sorted_rings, [&gctx](
const auto&
a,
const auto&
b) {
599 Acts::ProtoLayer pl_a(gctx, makeConstPtrVector(
a));
600 Acts::ProtoLayer pl_b(gctx, makeConstPtrVector(
b));
601 return std::abs(pl_a.min(AxisZ)) < std::abs(pl_b.min(AxisZ));
605 for (
size_t i = 0;
i < sorted_rings.size(); ++
i) {
606 const auto& surfaces = sorted_rings[
i];
610 if (
i < sorted_rings.size() - 1) {
611 ec_stack.addMaterial(layerName +
"_Material", [&](
auto&
mat) {
612 mat.configureFace(
bec > 0 ? PositiveDisc : NegativeDisc,
613 {AxisR, Bound, 20}, {AxisPhi, Bound, 40});
614 addEndcapLayer(
mat, layerName, surfaces);
617 addEndcapLayer(ec_stack, layerName, surfaces);