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