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 754 of file ItkBlueprintNodeBuilder.cxx.

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

◆ 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 216 of file ItkBlueprintNodeBuilder.cxx.

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

◆ 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 244 of file ItkBlueprintNodeBuilder.cxx.

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

◆ 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 626 of file ItkBlueprintNodeBuilder.cxx.

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

◆ initialize()

StatusCode ActsTrk::ItkBlueprintNodeBuilder::initialize ( )
override

Definition at line 205 of file ItkBlueprintNodeBuilder.cxx.

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

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:244
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:754
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:626
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