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

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

◆ 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 Calo should be null - no child expected");
222  throw std::runtime_error("Child node is not null");
223  }
224 
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 }

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

244  {
245 
246  // Get ITkPixel parameters from detector manager
247  if (!m_itkPixelMgr) {
248  ATH_MSG_ERROR("ITkPixel manager not available");
249  throw std::runtime_error("ITkPixel manager not available");
250  }
251 
252  ATH_MSG_DEBUG("Detector manager has "
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) {
264  ATH_MSG_ERROR("Detector element was nullptr");
265  throw std::runtime_error{"Corrupt detector element collection"};
266  }
267  elements.push_back(std::make_shared<ActsDetectorElement>(*siDetElement));
268  }
269  ATH_MSG_VERBOSE("Retrieved " << elements.size() << " elements");
270 
271  // Copy to service level store to extend lifetime
272  m_elementStore->vector().insert(m_elementStore->vector().end(),
273  elements.begin(), elements.end());
274 
275  // Create containers for inner and outer pixel parts
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  // Add barrel container
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();
306  if (id.bec() != 0) {
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 
318  ATH_MSG_DEBUG("Adding " << layers.size() << " layers to InnerPixel barrel");
319 
320  for (const auto& [ilayer, surfaces] : layers) {
321  ATH_MSG_DEBUG("- Layer " << ilayer << " has " << surfaces.size()
322  << " surfaces");
323 
324  barrel.addMaterial(
325  std::format("InnerPixel_Brl_{}_Material", ilayer), [&](auto& lmat) {
326  // Innermost layer: outer cylinder, else inner cylinder
327  lmat.configureFace(OuterCylinder, {AxisRPhi, Bound, 40},
328  {AxisZ, Bound, 20});
329 
330  // Add layer with surfaces
331  auto& layer =
332  lmat.addLayer(std::format("InnerPixel_Brl_{}", ilayer));
333 
334  // Set navigation policy for efficient surface lookup
335  layer.setNavigationPolicyFactory(
336  Acts::NavigationPolicyFactory{}
337  .add<Acts::SurfaceArrayNavigationPolicy>(
338  Acts::SurfaceArrayNavigationPolicy::Config{
339  .layerType = Cylinder,
340  .bins = {30, 10}}) // @TODO: Improve this logic
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  // Add endcap containers
355  for (int bec : {-2, 2}) { // Negative and positive endcaps
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; // Skip if not in the right endcap
372  }
373 
374  if (id.layer_disk() >= 3) {
375  continue; // Only include first 3 disks for inner pixel
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 
383  ATH_MSG_DEBUG("Found " << initialLayers.size()
384  << " initial layers to InnerPixel " << s << "EC");
385 
386  // Create proto layers from surfaces
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  // Sort by z position
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  // Merge overlapping layers
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  // Create layers from merged proto layers
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 
423  auto addLayer = [&layerName, &pl](auto& parent) {
424  // Add layer with surfaces
425  auto& layer = parent.addLayer(layerName);
426 
427  // Set navigation policy for efficient surface lookup
428  layer.setNavigationPolicyFactory(
429  Acts::NavigationPolicyFactory{}
430  .add<Acts::SurfaceArrayNavigationPolicy>(
431  Acts::SurfaceArrayNavigationPolicy::Config{
432  .layerType = Disc,
433  .bins = {30, 30}}) // @TODO: Improve this logic
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 
445  ATH_MSG_VERBOSE("Add inner pixel layer"
446  << key << " / " << mergedLayers.size()
447  << " at z = " << pl.protoLayer.medium(AxisZ));
448  if (key < mergedLayers.size() - 1) {
449  ATH_MSG_VERBOSE("Adding material for layer "
450  << layerName );
451  ec.addMaterial(layerName + "_Material", [&](auto& lmat) {
452  // Set binning for endcap layer
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  // Add outer pixel part
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  // Add barrel container
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();
482  if (id.bec() != 0) {
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 
494  ATH_MSG_DEBUG("Adding " << layers.size() << " layers to OuterPixel barrel");
495 
496  for (const auto& [ilayer, surfaces] : layers) {
497  ATH_MSG_DEBUG("- Layer " << ilayer << " has " << surfaces.size()
498  << " surfaces");
499 
500  barrel.addMaterial(
501  std::format("OuterPixel_Brl_{}_Material", ilayer), [&](auto& lmat) {
502  // Innermost layer: outer cylinder, else inner cylinder
503  lmat.configureFace(OuterCylinder, {AxisRPhi, Bound, 40},
504  {AxisZ, Bound, 20});
505 
506  // Add layer with surfaces
507  auto& layer =
508  lmat.addLayer("OuterPixel_Brl_" + std::to_string(ilayer));
509 
510  // Set navigation policy for efficient surface lookup
511  layer.setNavigationPolicyFactory(
512  Acts::NavigationPolicyFactory{}
513  .add<Acts::SurfaceArrayNavigationPolicy>(
514  Acts::SurfaceArrayNavigationPolicy::Config{
515  .layerType = Cylinder,
516  .bins = {30, 10}}) // @TODO: Improve this logic
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  // Add outer pixel endcaps
547  for (int bec : {-2, 2}) { // Negative and positive endcaps
548  const std::string s = bec > 0 ? "p" : "n";
549 
550  // R stacked Z rings
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  // Three groups of disks stacked in R
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  // Group sensors by eta rings
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  // Sort rings by absolute z position
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  // Create layers from sorted rings
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 }

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

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

◆ 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:243
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:753
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
MuonR4::to_string
std::string to_string(const SectorProjector proj)
Definition: MsTrackSeeder.cxx:66
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
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:625
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:24
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