244 {
245
246
249 throw std::runtime_error("ITkPixel manager not available");
250 }
251
254 << " elements");
255
256 std::vector<std::shared_ptr<ActsDetectorElement>> elements;
257
259 for (const auto* element :
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, Bound, 20}, {AxisZ, Bound, 20});
278
279 auto& innerPixelContainer =
mat.addCylinderContainer(
"InnerPixel", AxisZ);
280
281
282 auto& barrelGeoId = innerPixelContainer.withGeometryIdentifier();
283 barrelGeoId.setAllVolumeIdsTo(s_innerPixelVolumeId)
284 .incrementLayerIds(1)
285 .sortBy([](
auto&
a,
auto& b) {
286 auto& boundsA =
287 dynamic_cast<const Acts::CylinderVolumeBounds&
>(
a.volumeBounds());
288 auto& boundsB =
289 dynamic_cast<const Acts::CylinderVolumeBounds&
>(
b.volumeBounds());
290
291 using enum Acts::CylinderVolumeBounds::BoundValues;
292 double aMidR = (boundsA.get(eMinR) + boundsA.get(eMaxR)) / 2.0;
293 double bMidR = (boundsB.get(eMinR) + boundsB.get(eMaxR)) / 2.0;
294
295 return aMidR < bMidR;
296 });
297
298 auto&
barrel = barrelGeoId.addCylinderContainer(
"InnerPixel_Brl", AxisR);
299 barrel.setAttachmentStrategy(AttachmentStrategy::Gap);
300 barrel.setResizeStrategy(ResizeStrategy::Gap);
301
302 std::map<int, std::vector<std::shared_ptr<Acts::Surface>>>
layers{};
303
304 for (auto& element : elements) {
305 IdentityHelper id = element->identityHelper();
307 continue;
308 }
309
310 if (id.layer_disk() >= 2) {
311 continue;
312 }
313
314 int elementLayer = id.layer_disk();
315 layers[elementLayer].push_back(element->surface().getSharedPtr());
316 }
317
319
320 for (const auto& [ilayer, surfaces] : layers) {
321 ATH_MSG_DEBUG(
"- Layer " << ilayer <<
" has " << surfaces.size()
322 << " surfaces");
323
325 std::format("InnerPixel_Brl_{}_Material", ilayer), [&](auto& lmat) {
326
327 lmat.configureFace(OuterCylinder, {AxisRPhi, Bound, 40},
328 {AxisZ, Bound, 20});
329
330
332 lmat.addLayer(std::format("InnerPixel_Brl_{}", ilayer));
333
334
335 layer.setNavigationPolicyFactory(
336 Acts::NavigationPolicyFactory{}
337 .add<Acts::SurfaceArrayNavigationPolicy>(
338 Acts::SurfaceArrayNavigationPolicy::Config{
340 .bins = {30, 10}})
341 .add<Acts::TryAllNavigationPolicy>(
342 Acts::TryAllNavigationPolicy::Config{.sensitives =
343 false})
344 .asUniquePtr());
345
346 layer.setSurfaces(surfaces);
347 layer.setEnvelope(Acts::ExtentEnvelope{{
348 .z = {5_mm, 5_mm},
349 .r = {2_mm, 2_mm},
350 }});
351 });
352 }
353
354
355 for (int bec : {-2, 2}) {
356 std::string
s =
bec > 0 ?
"p" :
"n";
357 auto& ecGeoId = innerPixelContainer.withGeometryIdentifier();
358 ecGeoId.setAllVolumeIdsTo(s_innerPixelVolumeId + std::floor(bec / 2))
359 .incrementLayerIds(1);
360 auto& ec = ecGeoId.addCylinderContainer("InnerPixel_" + s + "EC", AxisZ);
361 ec.setAttachmentStrategy(AttachmentStrategy::Gap);
362 ec.setResizeStrategy(ResizeStrategy::Expand);
363
364 std::map<std::tuple<int, int, int>,
365 std::vector<std::shared_ptr<Acts::Surface>>>
366 initialLayers{};
367
368 for (auto& element : elements) {
369 IdentityHelper id = element->identityHelper();
370 if (
id.
bec() * bec <= 0) {
371 continue;
372 }
373
374 if (id.layer_disk() >= 3) {
375 continue;
376 }
377
378 std::tuple<int, int, int>
key{
id.bec(),
id.layer_disk(),
379 id.eta_module()};
380 initialLayers[
key].push_back(element->surface().getSharedPtr());
381 }
382
384 << " initial layers to InnerPixel " << s << "EC");
385
386
387 std::vector<LayerData> protoLayers;
388 protoLayers.reserve(initialLayers.size());
389
390 for (const auto& [key, surfaces] : initialLayers) {
391 auto&
layer = protoLayers.emplace_back(gctx, surfaces);
392 layer.protoLayer.envelope[AxisR] = {2_mm, 2_mm};
393 layer.protoLayer.envelope[AxisZ] = {1_mm, 1_mm};
394 }
395
396
397 std::ranges::sort(protoLayers,
398 [](
const LayerData&
a,
const LayerData& b) {
399 return std::abs(
a.protoLayer.medium(AxisZ)) <
400 std::abs(
b.protoLayer.medium(AxisZ));
401 });
402
403 ATH_MSG_DEBUG(
"Found " << protoLayers.size() <<
" initial layers");
404
405
406 std::vector<LayerData> mergedLayers;
408 mergedLayers = mergeLayers(gctx, std::move(protoLayers));
409 } else {
410 mergedLayers = std::move(protoLayers);
411 }
412
413 ATH_MSG_DEBUG(
"After merging: " << mergedLayers.size() <<
" layers");
414
415
416 for (const auto [key, pl] : Acts::enumerate(mergedLayers)) {
417 ATH_MSG_DEBUG(
"- Layer " << key <<
" has " << pl.surfaces.size()
418 << " surfaces");
419
420 pl.protoLayer.medium(AxisZ);
421 auto layerName = std::format(
"InnerPixel_{}EC_{}", key, s);
422
424
426
427
428 layer.setNavigationPolicyFactory(
429 Acts::NavigationPolicyFactory{}
430 .add<Acts::SurfaceArrayNavigationPolicy>(
431 Acts::SurfaceArrayNavigationPolicy::Config{
433 .bins = {30, 30}})
434 .add<Acts::TryAllNavigationPolicy>(
435 Acts::TryAllNavigationPolicy::Config{.sensitives = false})
436 .asUniquePtr());
437
438 layer.setSurfaces(pl.surfaces);
439 layer.setEnvelope(Acts::ExtentEnvelope{{
440 .z = {1_mm, 1_mm},
441 .r = {2_mm, 2_mm},
442 }});
443 };
444
446 << key << " / " << mergedLayers.size()
447 << " at z = " << pl.protoLayer.medium(AxisZ));
448 if (key < mergedLayers.size() - 1) {
450 << layerName );
451 ec.addMaterial(layerName + "_Material", [&](auto& lmat) {
452
453 lmat.configureFace(bec < 0 ? NegativeDisc : PositiveDisc,
454 {AxisR, Bound, 40}, {AxisPhi, Bound, 40});
455 addLayer(lmat);
456 });
457 } else {
458 addLayer(ec);
459 }
460 }
461 }
462 });
463
464
465 node.addMaterial(
"OuterPixelMaterial", [&](
auto& mat) {
466 mat.configureFace(OuterCylinder, {AxisRPhi, Bound, 20}, {AxisZ, Bound, 20});
467
468 auto& outerPixelContainer =
mat.addCylinderContainer(
"OuterPixel", AxisZ);
469
470
471 auto& barrelGeoId = outerPixelContainer.withGeometryIdentifier();
472 barrelGeoId.setAllVolumeIdsTo(s_outerPixelVolumeId).incrementLayerIds(1);
473
474 auto&
barrel = barrelGeoId.addCylinderContainer(
"OuterPixel_Brl", AxisR);
475 barrel.setAttachmentStrategy(AttachmentStrategy::Gap);
476 barrel.setResizeStrategy(ResizeStrategy::Gap);
477
478 std::map<int, std::vector<std::shared_ptr<Acts::Surface>>>
layers{};
479
480 for (auto& element : elements) {
481 IdentityHelper id = element->identityHelper();
483 continue;
484 }
485
486 if (id.layer_disk() <= 1) {
487 continue;
488 }
489
490 int elementLayer = id.layer_disk();
491 layers[elementLayer].push_back(element->surface().getSharedPtr());
492 }
493
495
496 for (const auto& [ilayer, surfaces] : layers) {
497 ATH_MSG_DEBUG(
"- Layer " << ilayer <<
" has " << surfaces.size()
498 << " surfaces");
499
501 std::format("OuterPixel_Brl_{}_Material", ilayer), [&](auto& lmat) {
502
503 lmat.configureFace(OuterCylinder, {AxisRPhi, Bound, 40},
504 {AxisZ, Bound, 20});
505
506
508 lmat.addLayer("OuterPixel_Brl_" + std::to_string(ilayer));
509
510
511 layer.setNavigationPolicyFactory(
512 Acts::NavigationPolicyFactory{}
513 .add<Acts::SurfaceArrayNavigationPolicy>(
514 Acts::SurfaceArrayNavigationPolicy::Config{
516 .bins = {30, 10}})
517 .add<Acts::TryAllNavigationPolicy>(
518 Acts::TryAllNavigationPolicy::Config{.sensitives =
519 false})
520 .asUniquePtr());
521
522 layer.setSurfaces(surfaces);
523 layer.setEnvelope(Acts::ExtentEnvelope{{
524 .z = {5_mm, 5_mm},
525 .r = {2_mm, 2_mm},
526 }});
527 });
528 }
529
530 constexpr static auto addEndcapLayer = [](
auto&
parent,
const auto&
name,
531 const auto& surfaces) {
532 parent.addLayer(name, [&surfaces](
auto& layer) {
533 layer.setNavigationPolicyFactory(
534 Acts::NavigationPolicyFactory{}
535 .add<Acts::SurfaceArrayNavigationPolicy>(
536 Acts::SurfaceArrayNavigationPolicy::Config{
537 .layerType =
Disc, .bins = {30, 30}})
538 .add<Acts::TryAllNavigationPolicy>(
539 Acts::TryAllNavigationPolicy::Config{.sensitives = false})
540 .asUniquePtr());
541
542 layer.setSurfaces(surfaces);
543 });
544 };
545
546
547 for (int bec : {-2, 2}) {
548 const std::string
s =
bec > 0 ?
"p" :
"n";
549
550
551
552 auto& ec_outer_geoId = outerPixelContainer.withGeometryIdentifier();
553 ec_outer_geoId
554 .setAllVolumeIdsTo(s_outerPixelVolumeId + std::floor(bec / 2))
555 .incrementLayerIds(1);
556
557 auto& ec_outer =
558 ec_outer_geoId.addCylinderContainer("OuterPixel_" + s + "EC", AxisR);
559
560
561 std::array diskGroups{std::pair{3, 4}, std::pair{6, 5}, std::pair{7, 8}};
562
563 for (
size_t idx = 0;
idx < diskGroups.size(); ++
idx) {
564 auto [disk1, disk2] = diskGroups[
idx];
565
566 auto& ec_stack = ec_outer.addCylinderContainer(
567 "OuterPixel_" + s + "EC_" + std::to_string(idx), AxisZ);
568
569 ec_stack.setAttachmentStrategy(AttachmentStrategy::Gap);
570 ec_stack.setResizeStrategy(ResizeStrategy::Expand);
571
572
573 std::map<std::tuple<int, int>,
574 std::vector<std::shared_ptr<Acts::Surface>>>
575 eta_rings;
576
577 for (auto& element : elements) {
578 IdentityHelper id = element->identityHelper();
579 if (
id.
bec() != bec ||
580 (id.layer_disk() != disk1 && id.layer_disk() != disk2)) {
581 continue;
582 }
583 std::tuple<int, int>
key{
id.layer_disk(),
id.eta_module()};
584 eta_rings[
key].push_back(element->surface().getSharedPtr());
585 }
586
587 ATH_MSG_DEBUG(
"Found " << eta_rings.size() <<
" eta rings in group "
588 << idx);
589
590
591 std::vector<std::vector<std::shared_ptr<Acts::Surface>>> sorted_rings;
592 sorted_rings.reserve(eta_rings.size());
593 for (const auto& [key, surfaces] : eta_rings) {
594 sorted_rings.push_back(surfaces);
595 }
596
597 std::ranges::sort(sorted_rings, [&gctx](
const auto&
a,
const auto& b) {
598 Acts::ProtoLayer pl_a(gctx, makeConstPtrVector(
a));
599 Acts::ProtoLayer pl_b(gctx, makeConstPtrVector(b));
600 return std::abs(pl_a.min(AxisZ)) < std::abs(pl_b.min(AxisZ));
601 });
602
603
604 for (
size_t i = 0;
i < sorted_rings.size(); ++
i) {
605 const auto& surfaces = sorted_rings[
i];
606 auto layerName =
"OuterPixel_" +
s +
"EC_" + std::to_string(idx) +
607 "_" + std::to_string(i);
608
609 if (i < sorted_rings.size() - 1) {
610 ec_stack.addMaterial(layerName + "_Material", [&](auto& mat) {
611 mat.configureFace(bec > 0 ? PositiveDisc : NegativeDisc,
612 {AxisR, Bound, 20}, {AxisPhi, Bound, 40});
613 addEndcapLayer(mat, layerName, surfaces);
614 });
615 } else {
616 addEndcapLayer(ec_stack, layerName, surfaces);
617 }
618 }
619 }
620 }
621 });
622
623}
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