ATLAS Offline Software
Public Member Functions | Private Member Functions | Private Attributes | List of all members
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::Experimental::BlueprintNode > buildBlueprintNode (const Acts::GeometryContext &gctx, std::shared_ptr< Acts::Experimental::BlueprintNode > &&child) override
 Build the Itk Blueprint Node. More...
 

Private Member Functions

void buildItkStripBlueprintNode (const Acts::GeometryContext &gctx, Acts::Experimental::BlueprintNode &node)
 Build the Itk Strip Blueprint Node. More...
 
void buildItkPixelBlueprintNode (const Acts::GeometryContext &gctx, Acts::Experimental::BlueprintNode &node)
 Build the Itk Pixel Blueprint Node. More...
 
void buildBeamPipeBlueprintNode (const Acts::GeometryContext &gctx, Acts::Experimental::BlueprintNode &node)
 Build the Beam Pipe Blueprint Node. More...
 

Private Attributes

const InDetDD::SiDetectorManagerm_itkPixelMgr {nullptr}
 
const InDetDD::SiDetectorManagerm_itkStripMgr {nullptr}
 
const BeamPipeDetectorManagerm_beamPipeMgr {nullptr}
 
std::shared_ptr< ActsElementVectorm_elementStore {nullptr}
 
Gaudi::Property< bool > m_doEndcapLayerMerging {this, "doEndcapLayerMerging", true}
 
Gaudi::Property< bool > m_buildBeamPipe {this, "buildBeamPipe", true}
 

Detailed Description

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

Definition at line 24 of file ItkBlueprintNodeBuilder.h.

Member Function Documentation

◆ buildBeamPipeBlueprintNode()

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

Build the Beam Pipe Blueprint Node.

Parameters
gctxGeometry context
nodeThe node to add the beam pipe node to

Definition at line 755 of file ItkBlueprintNodeBuilder.cxx.

756  {
757 
758 
759  // Get beam pipe parameters from existing code
760  PVConstLink beamPipeTopVolume = m_beamPipeMgr->getTreeTop(0);
761  if (m_beamPipeMgr->getNumTreeTops() == 1) {
762  beamPipeTopVolume =
763  m_beamPipeMgr->getTreeTop(0)->getChildVol(0)->getChildVol(0);
764  }
765 
766  const Amg::Transform3D beamPipeTransform{Amg::getTranslate3D(beamPipeTopVolume->getX().translation())};
767 
768  // Extract radius similar to makeBeamPipeConfig
769  double beamPipeRadius = 20; // Default value
770 
771  const GeoLogVol* beamPipeLogVolume = beamPipeTopVolume->getLogVol();
772  // This should always be set, but let's be safe
773  if (beamPipeLogVolume == nullptr) {
774  ATH_MSG_ERROR("Beam pipe volume has no log volume");
775  throw std::runtime_error("Beam pipe volume has no log volume");
776  }
777 
778  // Get the geoShape and translate
779  const GeoTube* beamPipeTube =
780  dynamic_cast<const GeoTube*>(beamPipeLogVolume->getShape());
781  if (beamPipeTube == nullptr) {
782  ATH_MSG_ERROR("BeamPipeLogVolume was not of type GeoTube");
783  throw std::runtime_error{"BeamPipeLogVolume was not of type GeoTube"};
784  }
785 
786  // Look for SectionC03 to get the actual radius
787  for (unsigned int i = 0; i < beamPipeTopVolume->getNChildVols(); i++) {
788  auto childName = beamPipeTopVolume->getNameOfChildVol(i);
789  if (childName != "SectionC03") {
790  continue; // Skip if not SectionC03
791  }
792  PVConstLink childTopVolume = beamPipeTopVolume->getChildVol(i);
793  const GeoLogVol* childLogVolume = childTopVolume->getLogVol();
794  const GeoTube* childTube =
795  dynamic_cast<const GeoTube*>(childLogVolume->getShape());
796  if (childTube) {
797  beamPipeRadius = 0.5 * (childTube->getRMax() + childTube->getRMin());
798  break;
799  }
800 
801  }
802 
803 
805  "BeamPipe constructed from Database: translation (yes) - radius "
806  << (beamPipeTube ? "(yes)" : "(no)") << " - r = " << beamPipeRadius);
807 
808  ATH_MSG_VERBOSE("BeamPipe shift estimated as : "
809  << beamPipeTransform.translation().transpose());
810 
811  // Add to blueprint following pattern from blueprint_itk.py
812  node.withGeometryIdentifier([&](auto& geoId) {
813  geoId.setAllVolumeIdsTo(s_beamPipeVolumeId);
814 
815  geoId.addMaterial("BeamPipe_Material", [&](auto& mat) {
816  mat.configureFace(OuterCylinder, {AxisRPhi, Bound, 20},
817  {AxisZ, Bound, 20});
818 
819  // Add static volume for beam pipe
820  mat.addStaticVolume(beamPipeTransform,
821  std::make_shared<Acts::CylinderVolumeBounds>(
822  0, beamPipeRadius * 1_mm, 3 * 1_m),
823  "BeamPipe");
824  });
825  });
826 }

◆ buildBlueprintNode()

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

Build the Itk Blueprint Node.

Parameters
gctxGeometry context
childThe child node which is added to the itk node.

Definition at line 217 of file ItkBlueprintNodeBuilder.cxx.

218  {
219 
220  if(childNode) {
221  ATH_MSG_ERROR("Child node for the Itk should be null - no child expected");
222  throw std::runtime_error("Child node is not null");
223  }
224 
225  // The itk node is a container node that will hold both the pixel and strip nodes
226  auto itkNode = std::make_shared<Acts::Experimental::CylinderContainerBlueprintNode>("ItkNode", AxisR);
227 
228  // Add the itk pixel to the node
229  buildItkPixelBlueprintNode(gctx, *itkNode);
230 
231  // Add the itk strip to the node
232  buildItkStripBlueprintNode(gctx, *itkNode);
233 
234  //Add the beam pipe to the node
235  if(m_buildBeamPipe) {
236 
237  buildBeamPipeBlueprintNode(gctx, *itkNode);
238 
239  }
240 
241  return itkNode;
242 
243 }

◆ buildItkPixelBlueprintNode()

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

Build the Itk Pixel Blueprint Node.

Parameters
gctxGeometry context
nodeThe node to add the pixel node to

Definition at line 245 of file ItkBlueprintNodeBuilder.cxx.

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

◆ buildItkStripBlueprintNode()

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

Build the Itk Strip Blueprint Node.

Parameters
gctxGeometry context
nodeThe node to add the strip node to

Definition at line 627 of file ItkBlueprintNodeBuilder.cxx.

628  {
629 
630  // Get ITkStrip parameters from detector manager
631  if (!m_itkStripMgr) {
632  ATH_MSG_ERROR("ITkStrip manager not available");
633  throw std::runtime_error("ITkStrip manager not available");
634  }
635 
636  ATH_MSG_DEBUG("Detector manager has "
638  << " elements");
639 
640  std::vector<std::shared_ptr<ActsDetectorElement>> elements;
641 
643  for (const auto* element :
645  const InDetDD::SiDetectorElement* siDetElement =
646  dynamic_cast<const InDetDD::SiDetectorElement*>(element);
647  if (siDetElement == nullptr) {
648  ATH_MSG_ERROR("Detector element was nullptr");
649  throw std::runtime_error{"Corrupt detector element collection"};
650  }
651  elements.push_back(std::make_shared<ActsDetectorElement>(*siDetElement));
652  }
653  ATH_MSG_VERBOSE("Retrieved " << elements.size() << " elements");
654 
655  // Copy to service level store to extend lifetime
656  m_elementStore->vector().insert(m_elementStore->vector().end(),
657  elements.begin(), elements.end());
658 
659  // Create container for strip part
660  node.addMaterial("StripMaterial", [&](auto& mat) {
661  mat.configureFace(OuterCylinder, {AxisRPhi, Bound, 20}, {AxisZ, Bound, 20});
662 
663  mat.addCylinderContainer("Strip", AxisZ, [&](auto& strips) {
664  // Add barrel container
665  strips.withGeometryIdentifier([this, &elements](auto& geoId) {
666  geoId.setAllVolumeIdsTo(s_stripVolumeId).incrementLayerIds(1);
667 
668  geoId.addCylinderContainer(
669  "Strip_Brl", AxisR, [this, &elements](auto& barrel) {
670  barrel.setAttachmentStrategy(AttachmentStrategy::Gap);
671  barrel.setResizeStrategy(ResizeStrategy::Gap);
672 
673  std::map<int, std::vector<std::shared_ptr<Acts::Surface>>>
674  layers{};
675 
676  for (auto& element : elements) {
677  IdentityHelper id = element->identityHelper();
678  if (id.bec() != 0) {
679  continue;
680  }
681 
682  int elementLayer = id.layer_disk();
683  layers[elementLayer].push_back(
684  element->surface().getSharedPtr());
685  }
686 
687  ATH_MSG_DEBUG("Adding " << layers.size()
688  << " layers to Strip barrel");
689 
690  for (const auto& [ilayer, surfaces] : layers) {
691  ATH_MSG_DEBUG("- Layer " << ilayer << " has " << surfaces.size()
692  << " surfaces");
693  addStripBarrelLayer(barrel, ilayer, surfaces);
694  }
695  });
696  });
697 
698  // Add endcap containers
699  for (int bec : {-2, 2}) { // Negative and positive endcaps
700  const std::string s = bec > 0 ? "p" : "n";
701 
702  std::map<int, std::vector<std::shared_ptr<Acts::Surface>>> layers{};
703 
704  for (auto& element : elements) {
705  IdentityHelper id = element->identityHelper();
706  if (id.bec() * bec <= 0) {
707  continue; // Skip if not in the right endcap
708  }
709 
710  layers[id.layer_disk()].push_back(element->surface().getSharedPtr());
711  }
712 
713  ATH_MSG_DEBUG("Found " << layers.size() << " layers in Strip " << s
714  << "EC");
715 
716  // Sort layers by absolute z position
717  std::vector<std::vector<std::shared_ptr<Acts::Surface>>> sorted_layers;
718  sorted_layers.reserve(layers.size());
719  for (const auto& [key, surfaces] : layers) {
720  sorted_layers.push_back(surfaces);
721  }
722 
723  std::sort(sorted_layers.begin(), sorted_layers.end(),
724  [&gctx](const auto& a, const auto& b) {
725  Acts::ProtoLayer pl_a(gctx, makeConstPtrVector(a));
726  Acts::ProtoLayer pl_b(gctx, makeConstPtrVector(b));
727  return std::abs(pl_a.min(AxisZ)) <
728  std::abs(pl_b.min(AxisZ));
729  });
730 
731  strips.withGeometryIdentifier([&sorted_layers, bec, &s](auto& geoId) {
732  geoId.setAllVolumeIdsTo(s_stripVolumeId + std::floor(bec / 2))
733  .incrementLayerIds(1);
734 
735  geoId.addCylinderContainer(
736  "Strip_" + s + "EC", AxisZ, [&sorted_layers, bec, &s](auto& ec) {
737  ec.setAttachmentStrategy(AttachmentStrategy::Gap);
738  ec.setResizeStrategy(ResizeStrategy::Gap);
739 
740  // Create layers from sorted layers
741  for (size_t i = 0; i < sorted_layers.size(); ++i) {
742  const auto& surfaces = sorted_layers[i];
743  auto layerName = "Strip_" + s + "EC_" + std::to_string(i);
744 
745  addStripEndcapLayer(ec, bec, layerName, surfaces);
746  }
747  });
748  });
749  }
750 
751  });
752  });
753  }

◆ initialize()

StatusCode ActsTrk::ItkBlueprintNodeBuilder::initialize ( )
override

Definition at line 206 of file ItkBlueprintNodeBuilder.cxx.

206  {
207  ATH_CHECK(detStore()->retrieve(m_itkStripMgr, "ITkStrip"));
208  ATH_CHECK(detStore()->retrieve(m_itkPixelMgr, "ITkPixel"));
209  if(m_buildBeamPipe) {
210  ATH_CHECK(detStore()->retrieve(m_beamPipeMgr, "BeamPipe"));
211  }
212  m_elementStore = std::make_shared<ActsElementVector>();
213  return StatusCode::SUCCESS;
214 
215 }

Member Data Documentation

◆ m_beamPipeMgr

const BeamPipeDetectorManager* ActsTrk::ItkBlueprintNodeBuilder::m_beamPipeMgr {nullptr}
private

Definition at line 44 of file ItkBlueprintNodeBuilder.h.

◆ m_buildBeamPipe

Gaudi::Property<bool> ActsTrk::ItkBlueprintNodeBuilder::m_buildBeamPipe {this, "buildBeamPipe", true}
private

Definition at line 50 of file ItkBlueprintNodeBuilder.h.

◆ m_doEndcapLayerMerging

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

Definition at line 48 of file ItkBlueprintNodeBuilder.h.

◆ m_elementStore

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

Definition at line 46 of file ItkBlueprintNodeBuilder.h.

◆ m_itkPixelMgr

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

Definition at line 40 of file ItkBlueprintNodeBuilder.h.

◆ m_itkStripMgr

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

Definition at line 42 of file ItkBlueprintNodeBuilder.h.


The documentation for this class was generated from the following files:
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
createLinkingScheme.iter
iter
Definition: createLinkingScheme.py:62
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
vtune_athena.format
format
Definition: vtune_athena.py:14
ActsTrk::ItkBlueprintNodeBuilder::buildItkPixelBlueprintNode
void buildItkPixelBlueprintNode(const Acts::GeometryContext &gctx, Acts::Experimental::BlueprintNode &node)
Build the Itk Pixel Blueprint Node.
Definition: ItkBlueprintNodeBuilder.cxx:245
ParticleGun_SamplingFraction.bec
int bec
Definition: ParticleGun_SamplingFraction.py:89
ActsTrk::ItkBlueprintNodeBuilder::m_elementStore
std::shared_ptr< ActsElementVector > m_elementStore
Definition: ItkBlueprintNodeBuilder.h:46
mat
GeoMaterial * mat
Definition: LArDetectorConstructionTBEC.cxx:55
IdentityHelper::layer_disk
int layer_disk() const
Definition: IdentityHelper.cxx:49
module_driven_slicing.layers
layers
Definition: module_driven_slicing.py:113
BeamPipeDetectorManager::getNumTreeTops
virtual unsigned int getNumTreeTops() const
Definition: BeamPipeDetectorManager.cxx:15
ReadBchFromCool.barrel
barrel
Definition: ReadBchFromCool.py:405
InDetDD::SiDetectorManager::getDetectorElementCollection
virtual const SiDetectorElementCollection * getDetectorElementCollection() const =0
access to whole collectiom
ActsTrk::ItkBlueprintNodeBuilder::buildBeamPipeBlueprintNode
void buildBeamPipeBlueprintNode(const Acts::GeometryContext &gctx, Acts::Experimental::BlueprintNode &node)
Build the Beam Pipe Blueprint Node.
Definition: ItkBlueprintNodeBuilder.cxx:755
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
BeamPipeDetectorManager::getTreeTop
virtual PVConstLink getTreeTop(unsigned int i) const
Definition: BeamPipeDetectorManager.cxx:20
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
test_pyathena.parent
parent
Definition: test_pyathena.py:15
xAOD::Disc
@ Disc
Definition: TrackingPrimitives.h:555
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
ActsTrk::ItkBlueprintNodeBuilder::m_beamPipeMgr
const BeamPipeDetectorManager * m_beamPipeMgr
Definition: ItkBlueprintNodeBuilder.h:44
lumiFormat.array
array
Definition: lumiFormat.py:91
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
xAOD::Cylinder
@ Cylinder
Definition: TrackingPrimitives.h:554
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
Muon::MuonStationIndex::layerName
const std::string & layerName(LayerIndex index)
convert LayerIndex into a string
Definition: MuonStationIndex.cxx:153
InDetDD::SiDetectorElement
Definition: SiDetectorElement.h:109
ActsTrk::ItkBlueprintNodeBuilder::m_buildBeamPipe
Gaudi::Property< bool > m_buildBeamPipe
Definition: ItkBlueprintNodeBuilder.h:50
ActsTrk::ItkBlueprintNodeBuilder::m_itkStripMgr
const InDetDD::SiDetectorManager * m_itkStripMgr
Definition: ItkBlueprintNodeBuilder.h:42
a
TList * a
Definition: liststreamerinfos.cxx:10
std::sort
void sort(typename std::reverse_iterator< DataModel_detail::iterator< DVL > > beg, typename std::reverse_iterator< DataModel_detail::iterator< DVL > > end, const Compare &comp)
Specialization of sort for DataVector/List.
Definition: DVL_algorithms.h:623
ActsTrk::ItkBlueprintNodeBuilder::buildItkStripBlueprintNode
void buildItkStripBlueprintNode(const Acts::GeometryContext &gctx, Acts::Experimental::BlueprintNode &node)
Build the Itk Strip Blueprint Node.
Definition: ItkBlueprintNodeBuilder.cxx:627
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
ActsTrk::ItkBlueprintNodeBuilder::m_itkPixelMgr
const InDetDD::SiDetectorManager * m_itkPixelMgr
Definition: ItkBlueprintNodeBuilder.h:40
ActsTrk::ItkBlueprintNodeBuilder::m_doEndcapLayerMerging
Gaudi::Property< bool > m_doEndcapLayerMerging
Definition: ItkBlueprintNodeBuilder.h:48
IdentityHelper
Definition: IdentityHelper.h:14
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
node
Definition: node.h:21
Amg::getTranslate3D
Amg::Transform3D getTranslate3D(const double X, const double Y, const double Z)
: Returns a shift transformation along an arbitrary axis
Definition: GeoPrimitivesHelpers.h:289
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37