From c418116aa16ae9c4a77e4dc6c399a195bbb349af Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 9 Aug 2024 12:15:03 +0200 Subject: [PATCH 001/100] -------------------------------------------- From 632211520fe78314c334760b1b5440b4fa4869e0 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 9 Aug 2024 12:13:38 +0200 Subject: [PATCH 002/100] -------------------------------------------- From 016c5e84a3b6433cd95e3be3b89b6a3e611f8014 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 9 Aug 2024 12:15:03 +0200 Subject: [PATCH 003/100] -------------------------------------------- From b8698c5389ba6c631cbe9f7ee80c343a959aa013 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 27 Mar 2024 16:56:52 +0100 Subject: [PATCH 004/100] blueprint: wip building test --- Core/include/Acts/Geometry/BlueprintNode.hpp | 51 +++++++++ .../CylinderContainerBlueprintNode.hpp | 36 ++++++ .../Acts/Geometry/StaticBlueprintNode.hpp | 36 ++++++ Core/src/Geometry/CMakeLists.txt | 3 + .../CylinderContainerBlueprintNode.cpp | 26 +++++ Core/src/Geometry/StaticBlueprintNode.cpp | 46 ++++++++ .../Core/Geometry/BlueprintNodeTests.cpp | 105 ++++++++++++++++++ Tests/UnitTests/Core/Geometry/CMakeLists.txt | 1 + 8 files changed, 304 insertions(+) create mode 100644 Core/include/Acts/Geometry/BlueprintNode.hpp create mode 100644 Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp create mode 100644 Core/include/Acts/Geometry/StaticBlueprintNode.hpp create mode 100644 Core/src/Geometry/CylinderContainerBlueprintNode.cpp create mode 100644 Core/src/Geometry/StaticBlueprintNode.cpp create mode 100644 Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp new file mode 100644 index 00000000000..bcf54b488a4 --- /dev/null +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -0,0 +1,51 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include +#include +#include +#include + +namespace Acts { + +class Volume; +class TrackingVolume; + +class BlueprintNode { + public: + BlueprintNode(const std::string& name) : m_name(name) {} + + virtual ~BlueprintNode() = default; + + std::string name() const { return m_name; } + void setName(const std::string& name) { m_name = name; } + + virtual void toStream(std::ostream& os) const; + + virtual Volume& build() = 0; + + // @TODO: This should return the portal "shell" + virtual void connect(TrackingVolume& parent) = 0; + + void addChild(std::unique_ptr child) { + m_children.push_back(std::move(child)); + } + + const std::vector>& children() { + return m_children; + } + + private: + std::string m_name; + + std::vector> m_children{}; +}; + +}; // namespace Acts diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp new file mode 100644 index 00000000000..2f89b7d3866 --- /dev/null +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -0,0 +1,36 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Geometry/BlueprintNode.hpp" +#include "Acts/Geometry/CylinderVolumeStack.hpp" +#include "Acts/Utilities/BinningType.hpp" +namespace Acts { + +class CylinderContainerBlueprintNode : public BlueprintNode { + public: + CylinderContainerBlueprintNode( + const std::string& name, BinningValue direction, + CylinderVolumeStack::AttachmentStrategy attachmentStrategy = + CylinderVolumeStack::AttachmentStrategy::Midpoint, + CylinderVolumeStack::ResizeStrategy resizeStrategy = + CylinderVolumeStack::ResizeStrategy::Expand); + + Volume& build() override; + + void connect(TrackingVolume& parent) override; + + private: + BinningValue m_direction; + CylinderVolumeStack::AttachmentStrategy m_attachmentStrategy; + CylinderVolumeStack::ResizeStrategy m_resizeStrategy; + // CylinderVolumeStack m_stack; +}; + +} // namespace Acts diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp new file mode 100644 index 00000000000..bdf6d2679f2 --- /dev/null +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -0,0 +1,36 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Geometry/BlueprintNode.hpp" +#include "Acts/Geometry/TrackingVolume.hpp" + +namespace Acts { + +class StaticBlueprintNode : public BlueprintNode { + public: + StaticBlueprintNode(const std::string& name, + std::unique_ptr volume); + + Volume& build() override; + + void connect(TrackingVolume& parent) override; + + // This connects averything to the static volume contained here + void connect(); + + std::unique_ptr releaseVolume() { + return std::move(m_volume); + } + + private: + std::unique_ptr m_volume; +}; + +} // namespace Acts diff --git a/Core/src/Geometry/CMakeLists.txt b/Core/src/Geometry/CMakeLists.txt index 74f6e0e126d..7edcfecd2f1 100644 --- a/Core/src/Geometry/CMakeLists.txt +++ b/Core/src/Geometry/CMakeLists.txt @@ -43,4 +43,7 @@ target_sources( PortalLinkBase.cpp PortalError.cpp PortalShell.cpp + BlueprintNode.cpp + CylinderContainerBlueprintNode.cpp + StaticBlueprintNode.cpp ) diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp new file mode 100644 index 00000000000..a6ff6bded1e --- /dev/null +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -0,0 +1,26 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" + +namespace Acts { + +CylinderContainerBlueprintNode::CylinderContainerBlueprintNode( + const std::string& name, BinningValue direction, + CylinderVolumeStack::AttachmentStrategy attachmentStrategy, + CylinderVolumeStack::ResizeStrategy resizeStrategy) + : BlueprintNode(name), + m_direction(direction), + m_attachmentStrategy(attachmentStrategy), + m_resizeStrategy(resizeStrategy) {} + +Volume& CylinderContainerBlueprintNode::build() {} + +void CylinderContainerBlueprintNode::connect(TrackingVolume& parent) {} + +} // namespace Acts diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp new file mode 100644 index 00000000000..f8b78a416ce --- /dev/null +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -0,0 +1,46 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Geometry/StaticBlueprintNode.hpp" + +namespace Acts { + +StaticBlueprintNode::StaticBlueprintNode(const std::string& name, + std::unique_ptr volume) + : BlueprintNode(name), m_volume(std::move(volume)) {} + +Volume& StaticBlueprintNode::build() { + if (!m_volume) { + throw std::runtime_error("Volume is not set"); + } + + return *m_volume; +} + +void StaticBlueprintNode::connect(TrackingVolume& parent) { + if (!m_volume) { + throw std::runtime_error("Volume is not set"); + } + + for (auto& child : children()) { + child->connect(*m_volume); + } + parent.addVolume(std::move(m_volume)); +} + +void StaticBlueprintNode::connect() { + if (!m_volume) { + throw std::runtime_error("Volume is not set"); + } + + for (auto& child : children()) { + child->connect(*m_volume); + } +} + +} // namespace Acts diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp new file mode 100644 index 00000000000..e1700b55ce5 --- /dev/null +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -0,0 +1,105 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include +#include +#include +#include + +#include "Acts/Definitions/Algebra.hpp" +#include "Acts/Definitions/Units.hpp" +#include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/StaticBlueprintNode.hpp" +#include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Utilities/Logger.hpp" +#include "Acts/Visualization/GeometryView3D.hpp" +#include "Acts/Visualization/ObjVisualization3D.hpp" + +using namespace Acts::UnitLiterals; + +namespace Acts::Test { + +auto logger = Acts::getDefaultLogger("UnitTests", Acts::Logging::VERBOSE); + +GeometryContext gctx; + +BOOST_AUTO_TEST_SUITE(Geometry); + +BOOST_AUTO_TEST_SUITE(BlueprintNodeTest); + +BOOST_AUTO_TEST_CASE(StaticBlueprintNodeConstruction) { + ActsScalar hlZ = 30_mm; + auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); + auto cyl = + std::make_unique(Transform3::Identity(), cylBounds); + + const auto* cylPtr = cyl.get(); + + StaticBlueprintNode node("root", std::move(cyl)); + + BOOST_CHECK_EQUAL(node.name(), "root"); + node.setName("newroot"); + BOOST_CHECK_EQUAL(node.name(), "newroot"); + + BOOST_CHECK_EQUAL(&node.build(), cylPtr); + + ObjVisualization3D vis; + // Add some children + ActsScalar z0 = -200_mm; + for (std::size_t i = 0; i < 10; i++) { + auto childCyl = std::make_unique( + Transform3::Identity() * + Translation3{Vector3{0, 0, z0 + i * 2 * hlZ * 1.2}}, + cylBounds); + + GeometryView3D::drawVolume(vis, *childCyl, gctx); + + node.addChild(std::make_unique( + "child" + std::to_string(i), std::move(childCyl))); + } + + BOOST_CHECK_EQUAL(node.children().size(), 10); + + std::ofstream ofs{"static.obj"}; + vis.write(ofs); + + node.build(); + node.connect(); + + auto world = node.releaseVolume(); + + BOOST_CHECK_EQUAL(world->volumes().size(), 10); +} + +BOOST_AUTO_TEST_CASE(CylinderContainerNode) { + ActsScalar hlZ = 30_mm; + auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); + + auto root = std::make_unique( + "root", BinningValue::binZ); + + ActsScalar z0 = -200_mm; + for (std::size_t i = 0; i < 10; i++) { + auto childCyl = std::make_unique( + Transform3::Identity() * + Translation3{Vector3{0, 0, z0 + i * 2 * hlZ * 1.2}}, + cylBounds); + root->addChild(std::make_unique( + "child" + std::to_string(i), std::move(childCyl))); + } + + // auto world = root->build(); + // std::cout << world.volumeBounds() << std::endl; +} + +BOOST_AUTO_TEST_SUITE_END(); + +BOOST_AUTO_TEST_SUITE_END(); + +} // namespace Acts::Test diff --git a/Tests/UnitTests/Core/Geometry/CMakeLists.txt b/Tests/UnitTests/Core/Geometry/CMakeLists.txt index 0226e46d7d0..3c525768661 100644 --- a/Tests/UnitTests/Core/Geometry/CMakeLists.txt +++ b/Tests/UnitTests/Core/Geometry/CMakeLists.txt @@ -35,3 +35,4 @@ add_unittest(CylinderVolumeStack CylinderVolumeStackTests.cpp) add_unittest(PortalLink PortalLinkTests.cpp) add_unittest(Portal PortalTests.cpp) add_unittest(PortalShell PortalShellTests.cpp) +add_unittest(BlueprintNode BlueprintNodeTests.cpp) From 29426bccf5388127bcbc1323556dd62dc84e2ca6 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 27 Mar 2024 13:56:22 +0100 Subject: [PATCH 005/100] blueprint: basic hierarchy --- Core/include/Acts/Geometry/BlueprintNode.hpp | 37 +++++++++--- .../CylinderContainerBlueprintNode.hpp | 15 ++++- .../Acts/Geometry/StaticBlueprintNode.hpp | 11 +++- Core/src/Geometry/BlueprintNode.cpp | 47 +++++++++++++++ .../CylinderContainerBlueprintNode.cpp | 59 ++++++++++++++++++- Core/src/Geometry/StaticBlueprintNode.cpp | 38 +++++++++--- .../Core/Geometry/BlueprintNodeTests.cpp | 21 ++++++- 7 files changed, 201 insertions(+), 27 deletions(-) create mode 100644 Core/src/Geometry/BlueprintNode.cpp diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index bcf54b488a4..dba80667791 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -8,6 +8,10 @@ #pragma once +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Utilities/Logger.hpp" +#include "Acts/Utilities/TransformRange.hpp" + #include #include #include @@ -17,6 +21,7 @@ namespace Acts { class Volume; class TrackingVolume; +class IVisualization3D; class BlueprintNode { public: @@ -29,22 +34,38 @@ class BlueprintNode { virtual void toStream(std::ostream& os) const; - virtual Volume& build() = 0; + virtual Volume& build(const Logger& logger = Acts::getDummyLogger()) = 0; // @TODO: This should return the portal "shell" - virtual void connect(TrackingVolume& parent) = 0; + virtual void connect(TrackingVolume& parent, + const Logger& logger = Acts::getDummyLogger()) = 0; + + virtual void visualize(IVisualization3D& vis, + const GeometryContext& gctx) const; + + void addChild(std::unique_ptr child); + + using MutableChildRange = + detail::TransformRange>>; - void addChild(std::unique_ptr child) { - m_children.push_back(std::move(child)); - } + using ChildRange = + detail::TransformRange>>; - const std::vector>& children() { - return m_children; - } + MutableChildRange children(); + ChildRange children() const; + + std::size_t depth() const; + + protected: + std::string prefix() const; private: std::string m_name; + std::size_t m_depth{0}; + std::vector> m_children{}; }; diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index 2f89b7d3866..261b964df2b 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -11,6 +11,8 @@ #include "Acts/Geometry/BlueprintNode.hpp" #include "Acts/Geometry/CylinderVolumeStack.hpp" #include "Acts/Utilities/BinningType.hpp" +#include "Acts/Utilities/Logger.hpp" + namespace Acts { class CylinderContainerBlueprintNode : public BlueprintNode { @@ -22,15 +24,22 @@ class CylinderContainerBlueprintNode : public BlueprintNode { CylinderVolumeStack::ResizeStrategy resizeStrategy = CylinderVolumeStack::ResizeStrategy::Expand); - Volume& build() override; + Volume& build(const Logger& logger = Acts::getDummyLogger()) override; + + void connect(TrackingVolume& parent, + const Logger& logger = Acts::getDummyLogger()) override; - void connect(TrackingVolume& parent) override; + void visualize(IVisualization3D& vis, + const GeometryContext& gctx) const override; private: BinningValue m_direction; CylinderVolumeStack::AttachmentStrategy m_attachmentStrategy; CylinderVolumeStack::ResizeStrategy m_resizeStrategy; - // CylinderVolumeStack m_stack; + + // Is only initialized during `build` + std::vector m_childVolumes; + std::optional m_stack{std::nullopt}; }; } // namespace Acts diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index bdf6d2679f2..605ccfd1b00 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -9,6 +9,7 @@ #pragma once #include "Acts/Geometry/BlueprintNode.hpp" +#include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/TrackingVolume.hpp" namespace Acts { @@ -18,12 +19,16 @@ class StaticBlueprintNode : public BlueprintNode { StaticBlueprintNode(const std::string& name, std::unique_ptr volume); - Volume& build() override; + Volume& build(const Logger& logger = Acts::getDummyLogger()) override; - void connect(TrackingVolume& parent) override; + void connect(TrackingVolume& parent, + const Logger& logger = Acts::getDummyLogger()) override; + + void visualize(IVisualization3D& vis, + const GeometryContext& gctx) const override; // This connects averything to the static volume contained here - void connect(); + void connect(const Logger& logger = Acts::getDummyLogger()); std::unique_ptr releaseVolume() { return std::move(m_volume); diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp new file mode 100644 index 00000000000..e60803f36bc --- /dev/null +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -0,0 +1,47 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Geometry/BlueprintNode.hpp" + +#include + +namespace Acts { + +void BlueprintNode::toStream(std::ostream& os) const { + os << "BlueprintNode( " << name() << ")"; +} + +void BlueprintNode::addChild(std::unique_ptr child) { + child->m_depth = m_depth + 1; + m_children.push_back(std::move(child)); +} + +BlueprintNode::MutableChildRange BlueprintNode::children() { + return MutableChildRange{m_children}; +} + +BlueprintNode::ChildRange BlueprintNode::children() const { + return ChildRange{m_children}; +} + +std::size_t BlueprintNode::depth() const { + return m_depth; +} + +std::string BlueprintNode::prefix() const { + return std::string(m_depth * 2, ' ') + "[" + name() + "]: "; +} + +void BlueprintNode::visualize(IVisualization3D& vis, + const GeometryContext& gctx) const { + for (const auto& child : children()) { + child.visualize(vis, gctx); + } +} + +} // namespace Acts diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index a6ff6bded1e..74d5d063034 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -8,6 +8,11 @@ #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" +#include "Acts/Geometry/BlueprintNode.hpp" +#include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Visualization/GeometryView3D.hpp" +#include "Acts/Visualization/ViewConfig.hpp" + namespace Acts { CylinderContainerBlueprintNode::CylinderContainerBlueprintNode( @@ -19,8 +24,58 @@ CylinderContainerBlueprintNode::CylinderContainerBlueprintNode( m_attachmentStrategy(attachmentStrategy), m_resizeStrategy(resizeStrategy) {} -Volume& CylinderContainerBlueprintNode::build() {} +Volume& CylinderContainerBlueprintNode::build(const Logger& logger) { + ACTS_DEBUG(prefix() << "cylinder container build"); + + if (m_stack.has_value()) { + throw std::runtime_error("Volume is already built"); + } + + for (auto& child : children()) { + m_childVolumes.push_back(&child.build(logger)); + } + ACTS_VERBOSE(prefix() << "-> Collected " << m_childVolumes.size() + << " child volumes"); + + ACTS_VERBOSE(prefix() << "-> Building the stack"); + m_stack.emplace(m_childVolumes, m_direction, m_attachmentStrategy, + m_resizeStrategy, logger); + ACTS_DEBUG(prefix() << "-> Stack bounds are: " << m_stack->volumeBounds()); + + return m_stack.value(); +} + +void CylinderContainerBlueprintNode::connect(TrackingVolume& parent, + const Logger& logger) { + ACTS_DEBUG(prefix() << "cylinder container connect"); + if (!m_stack.has_value()) { + throw std::runtime_error("Volume is not built"); + } + + for (auto& child : children()) { + child.connect(parent); + } + + for (auto& gap : m_stack->gaps()) { + auto tv = std::make_unique(*gap); + parent.addVolume(std::move(tv)); + } +} + +void CylinderContainerBlueprintNode::visualize( + IVisualization3D& vis, const GeometryContext& gctx) const { + if (!m_stack.has_value()) { + throw std::runtime_error("Cylinder Stack Volume is not built"); + } + + ViewConfig viewConfig{{255, 0, 0}}; + + for (const auto& gap : m_stack->gaps()) { + GeometryView3D::drawVolume(vis, *gap, gctx, Transform3::Identity(), + viewConfig); + } -void CylinderContainerBlueprintNode::connect(TrackingVolume& parent) {} + BlueprintNode::visualize(vis, gctx); +} } // namespace Acts diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index f8b78a416ce..6b2894461cf 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -8,39 +8,61 @@ #include "Acts/Geometry/StaticBlueprintNode.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Visualization/GeometryView3D.hpp" +#include "Acts/Visualization/ViewConfig.hpp" + namespace Acts { StaticBlueprintNode::StaticBlueprintNode(const std::string& name, std::unique_ptr volume) : BlueprintNode(name), m_volume(std::move(volume)) {} -Volume& StaticBlueprintNode::build() { +Volume& StaticBlueprintNode::build(const Logger& logger) { + ACTS_DEBUG(prefix() << "static build"); if (!m_volume) { - throw std::runtime_error("Volume is not set"); + throw std::runtime_error("Volume is not built"); } + ACTS_DEBUG(prefix() << "-> returning volume " << *m_volume); return *m_volume; } -void StaticBlueprintNode::connect(TrackingVolume& parent) { +void StaticBlueprintNode::connect(TrackingVolume& parent, + const Logger& logger) { + ACTS_DEBUG(prefix() << "static connect") if (!m_volume) { - throw std::runtime_error("Volume is not set"); + throw std::runtime_error("Volume is not built"); } for (auto& child : children()) { - child->connect(*m_volume); + child.connect(*m_volume); } parent.addVolume(std::move(m_volume)); } -void StaticBlueprintNode::connect() { +void StaticBlueprintNode::connect(const Logger& logger) { + ACTS_DEBUG(prefix() << "static connect") if (!m_volume) { - throw std::runtime_error("Volume is not set"); + throw std::runtime_error("Volume is not built"); } for (auto& child : children()) { - child->connect(*m_volume); + child.connect(*m_volume); } } +void StaticBlueprintNode::visualize(IVisualization3D& vis, + const GeometryContext& gctx) const { + if (!m_volume) { + throw std::runtime_error("Volume is not built"); + } + + ViewConfig viewConfig{{100, 100, 100}}; + + GeometryView3D::drawVolume(vis, *m_volume, gctx, Transform3::Identity(), + viewConfig); + BlueprintNode::visualize(vis, gctx); +} + } // namespace Acts diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index e1700b55ce5..bcb3e5a9fa0 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -82,7 +82,8 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); auto root = std::make_unique( - "root", BinningValue::binZ); + "root", BinningValue::binZ, CylinderVolumeStack::AttachmentStrategy::Gap, + CylinderVolumeStack::ResizeStrategy::Gap); ActsScalar z0 = -200_mm; for (std::size_t i = 0; i < 10; i++) { @@ -94,8 +95,22 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { "child" + std::to_string(i), std::move(childCyl))); } - // auto world = root->build(); - // std::cout << world.volumeBounds() << std::endl; + TrackingVolume dummy{Transform3::Identity(), cylBounds}; + BOOST_CHECK_THROW(root->connect(dummy), std::runtime_error); + + ObjVisualization3D vis; + // Can't visualize before having called build + BOOST_CHECK_THROW(root->visualize(vis, gctx), std::runtime_error); + + auto world = root->build(*logger); + + root->visualize(vis, gctx); + + TrackingVolume top{world.transform(), world.volumeBoundsPtr()}; + + root->connect(top, *logger); + + vis.write("container.obj"); } BOOST_AUTO_TEST_SUITE_END(); From ac172474921d397776594b7480b8e526a83fea78 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 27 Mar 2024 15:38:02 +0100 Subject: [PATCH 006/100] blueprint: wip API --- Core/include/Acts/Geometry/BlueprintNode.hpp | 17 ++-- .../CylinderContainerBlueprintNode.hpp | 10 ++ .../Acts/Geometry/StaticBlueprintNode.hpp | 5 +- Core/src/Geometry/BlueprintNode.cpp | 20 ++++ Core/src/Geometry/CMakeLists.txt | 1 + .../CylinderContainerBlueprintNode.cpp | 35 ++++++- Core/src/Geometry/StaticBlueprintNode.cpp | 9 +- .../Core/Geometry/BlueprintNodeTests.cpp | 98 ++++++++++++++++--- 8 files changed, 172 insertions(+), 23 deletions(-) diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index dba80667791..ca158b78a4b 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -9,6 +9,7 @@ #pragma once #include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Utilities/TransformRange.hpp" @@ -22,15 +23,15 @@ namespace Acts { class Volume; class TrackingVolume; class IVisualization3D; +class CylinderContainerBlueprintNode; class BlueprintNode { public: - BlueprintNode(const std::string& name) : m_name(name) {} + BlueprintNode() = default; virtual ~BlueprintNode() = default; - std::string name() const { return m_name; } - void setName(const std::string& name) { m_name = name; } + virtual const std::string& name() const = 0; virtual void toStream(std::ostream& os) const; @@ -43,6 +44,13 @@ class BlueprintNode { virtual void visualize(IVisualization3D& vis, const GeometryContext& gctx) const; + void addStaticVolume(std::unique_ptr volume); + + void addCylinderContainer( + const std::string& name, BinningValue direction, + const std::function( + std::unique_ptr cylinder)>& factory); + void addChild(std::unique_ptr child); using MutableChildRange = @@ -62,10 +70,7 @@ class BlueprintNode { std::string prefix() const; private: - std::string m_name; - std::size_t m_depth{0}; - std::vector> m_children{}; }; diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index 261b964df2b..66a2ce475a1 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -24,6 +24,8 @@ class CylinderContainerBlueprintNode : public BlueprintNode { CylinderVolumeStack::ResizeStrategy resizeStrategy = CylinderVolumeStack::ResizeStrategy::Expand); + const std::string& name() const override; + Volume& build(const Logger& logger = Acts::getDummyLogger()) override; void connect(TrackingVolume& parent, @@ -32,7 +34,15 @@ class CylinderContainerBlueprintNode : public BlueprintNode { void visualize(IVisualization3D& vis, const GeometryContext& gctx) const override; + CylinderContainerBlueprintNode& setDirection(BinningValue direction); + CylinderContainerBlueprintNode& setAttachmentStrategy( + CylinderVolumeStack::AttachmentStrategy attachmentStrategy); + CylinderContainerBlueprintNode& setResizeStrategy( + CylinderVolumeStack::ResizeStrategy resizeStrategy); + private: + std::string m_name; + BinningValue m_direction; CylinderVolumeStack::AttachmentStrategy m_attachmentStrategy; CylinderVolumeStack::ResizeStrategy m_resizeStrategy; diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index 605ccfd1b00..2bfae3c2e69 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -16,8 +16,9 @@ namespace Acts { class StaticBlueprintNode : public BlueprintNode { public: - StaticBlueprintNode(const std::string& name, - std::unique_ptr volume); + StaticBlueprintNode(std::unique_ptr volume); + + const std::string& name() const override; Volume& build(const Logger& logger = Acts::getDummyLogger()) override; diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index e60803f36bc..512b9156bb9 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -8,6 +8,9 @@ #include "Acts/Geometry/BlueprintNode.hpp" +#include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" +#include "Acts/Geometry/StaticBlueprintNode.hpp" + #include namespace Acts { @@ -44,4 +47,21 @@ void BlueprintNode::visualize(IVisualization3D& vis, } } +void BlueprintNode::addStaticVolume(std::unique_ptr volume) { + addChild(std::make_unique(std::move(volume))); +} + +void BlueprintNode::addCylinderContainer( + const std::string& name, BinningValue direction, + const std::function( + std::unique_ptr cylinder)>& factory) { + auto cylinder = + std::make_unique(name, direction); + auto node = factory(std::move(cylinder)); + if (!node) { + throw std::runtime_error("Factory did not return a node"); + } + addChild(std::move(node)); +} + } // namespace Acts diff --git a/Core/src/Geometry/CMakeLists.txt b/Core/src/Geometry/CMakeLists.txt index 7edcfecd2f1..90f8efa876e 100644 --- a/Core/src/Geometry/CMakeLists.txt +++ b/Core/src/Geometry/CMakeLists.txt @@ -46,4 +46,5 @@ target_sources( BlueprintNode.cpp CylinderContainerBlueprintNode.cpp StaticBlueprintNode.cpp + Blueprint.cpp ) diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 74d5d063034..fcfa9d2c956 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -19,11 +19,15 @@ CylinderContainerBlueprintNode::CylinderContainerBlueprintNode( const std::string& name, BinningValue direction, CylinderVolumeStack::AttachmentStrategy attachmentStrategy, CylinderVolumeStack::ResizeStrategy resizeStrategy) - : BlueprintNode(name), + : m_name(name), m_direction(direction), m_attachmentStrategy(attachmentStrategy), m_resizeStrategy(resizeStrategy) {} +const std::string& CylinderContainerBlueprintNode::name() const { + return m_name; +} + Volume& CylinderContainerBlueprintNode::build(const Logger& logger) { ACTS_DEBUG(prefix() << "cylinder container build"); @@ -78,4 +82,33 @@ void CylinderContainerBlueprintNode::visualize( BlueprintNode::visualize(vis, gctx); } +CylinderContainerBlueprintNode& CylinderContainerBlueprintNode::setDirection( + BinningValue direction) { + if (m_stack.has_value()) { + throw std::runtime_error("Cannot change direction after build"); + } + m_direction = direction; + return *this; +} + +CylinderContainerBlueprintNode& +CylinderContainerBlueprintNode::setAttachmentStrategy( + CylinderVolumeStack::AttachmentStrategy attachmentStrategy) { + if (m_stack.has_value()) { + throw std::runtime_error("Cannot change direction after build"); + } + m_attachmentStrategy = attachmentStrategy; + return *this; +} + +CylinderContainerBlueprintNode& +CylinderContainerBlueprintNode::setResizeStrategy( + CylinderVolumeStack::ResizeStrategy resizeStrategy) { + if (m_stack.has_value()) { + throw std::runtime_error("Cannot change direction after build"); + } + m_resizeStrategy = resizeStrategy; + return *this; +} + } // namespace Acts diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index 6b2894461cf..cff0fdbdfd6 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -14,9 +14,8 @@ namespace Acts { -StaticBlueprintNode::StaticBlueprintNode(const std::string& name, - std::unique_ptr volume) - : BlueprintNode(name), m_volume(std::move(volume)) {} +StaticBlueprintNode::StaticBlueprintNode(std::unique_ptr volume) + : m_volume(std::move(volume)) {} Volume& StaticBlueprintNode::build(const Logger& logger) { ACTS_DEBUG(prefix() << "static build"); @@ -65,4 +64,8 @@ void StaticBlueprintNode::visualize(IVisualization3D& vis, BlueprintNode::visualize(vis, gctx); } +const std::string& StaticBlueprintNode::name() const { + return m_volume->volumeName(); +} + } // namespace Acts diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index bcb3e5a9fa0..0723e8c25b0 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -36,16 +36,14 @@ BOOST_AUTO_TEST_SUITE(BlueprintNodeTest); BOOST_AUTO_TEST_CASE(StaticBlueprintNodeConstruction) { ActsScalar hlZ = 30_mm; auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); - auto cyl = - std::make_unique(Transform3::Identity(), cylBounds); + auto cyl = std::make_unique(Transform3::Identity(), cylBounds, + "root"); const auto* cylPtr = cyl.get(); - StaticBlueprintNode node("root", std::move(cyl)); + StaticBlueprintNode node(std::move(cyl)); BOOST_CHECK_EQUAL(node.name(), "root"); - node.setName("newroot"); - BOOST_CHECK_EQUAL(node.name(), "newroot"); BOOST_CHECK_EQUAL(&node.build(), cylPtr); @@ -56,12 +54,11 @@ BOOST_AUTO_TEST_CASE(StaticBlueprintNodeConstruction) { auto childCyl = std::make_unique( Transform3::Identity() * Translation3{Vector3{0, 0, z0 + i * 2 * hlZ * 1.2}}, - cylBounds); + cylBounds, "child" + std::to_string(i)); GeometryView3D::drawVolume(vis, *childCyl, gctx); - node.addChild(std::make_unique( - "child" + std::to_string(i), std::move(childCyl))); + node.addChild(std::make_unique(std::move(childCyl))); } BOOST_CHECK_EQUAL(node.children().size(), 10); @@ -90,9 +87,8 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { auto childCyl = std::make_unique( Transform3::Identity() * Translation3{Vector3{0, 0, z0 + i * 2 * hlZ * 1.2}}, - cylBounds); - root->addChild(std::make_unique( - "child" + std::to_string(i), std::move(childCyl))); + cylBounds, "child" + std::to_string(i)); + root->addStaticVolume(std::move(childCyl)); } TrackingVolume dummy{Transform3::Identity(), cylBounds}; @@ -113,6 +109,86 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { vis.write("container.obj"); } +BOOST_AUTO_TEST_CASE(NodeApiTest) { + auto root = std::make_unique( + "root", BinningValue::binZ, CylinderVolumeStack::AttachmentStrategy::Gap, + CylinderVolumeStack::ResizeStrategy::Gap); + + root->addCylinderContainer("Pixel", binZ, [&](auto cyl) { + cyl->setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) + .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); + + // cyl->addStaticVolume(std::make_unique( + // Transform3::Identity() * Translation3{Vector3{0, 0, -600_mm}}, + // std::make_shared(200_mm, 400_mm, 200_mm), + // "PixelNegativeEndcap")); + + cyl->addCylinderContainer("PixelNegativeEndcap", binZ, [](auto ec) { + ec->setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap); + + ec->addStaticVolume(std::make_unique( + Transform3::Identity() * Translation3{Vector3{0, 0, -600_mm}}, + std::make_shared(200_mm, 450_mm, 20_mm), + "PixelNeg1")); + + ec->addStaticVolume(std::make_unique( + Transform3::Identity() * Translation3{Vector3{0, 0, -400_mm}}, + std::make_shared(200_mm, 800_mm, 20_mm), + "PixelNeg1")); + + return ec; + }); + + // cyl->addStaticVolume(std::make_unique( + // Transform3::Identity() * Translation3{Vector3{0, 0, 0_mm}}, + // std::make_shared(100_mm, 600_mm, 200_mm), + // "PixelBarrel")); + + cyl->addCylinderContainer("PixelBarrel", binR, [](auto brl) { + brl->setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) + .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Expand); + + brl->addStaticVolume(std::make_unique( + Transform3::Identity(), + std::make_shared(23_mm, 48_mm, 200_mm), + "PixelLayer0")); + + brl->addStaticVolume(std::make_unique( + Transform3::Identity(), + std::make_shared(87_mm, 103_mm, 250_mm), + "PixelLayer1")); + + brl->addStaticVolume(std::make_unique( + Transform3::Identity(), + std::make_shared(150_mm, 180_mm, 310_mm), + "PixelLayer2")); + + brl->addStaticVolume(std::make_unique( + Transform3::Identity(), + std::make_shared(250_mm, 400_mm, 310_mm), + "PixelLayer2")); + + return brl; + }); + + cyl->addCylinderContainer("PixelPoxWrapper", binR, [](auto ec) { + ec->setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); + ec->addStaticVolume(std::make_unique( + Transform3::Identity() * Translation3{Vector3{0, 0, 600_mm}}, + std::make_shared(150_mm, 390_mm, 200_mm), + "PixelPositiveEndcap")); + return ec; + }); + + return cyl; + }); + + auto world = root->build(*logger); + ObjVisualization3D vis; + root->visualize(vis, gctx); + vis.write("api_test.obj"); +} + BOOST_AUTO_TEST_SUITE_END(); BOOST_AUTO_TEST_SUITE_END(); From 4f86535b8ecdb984e3b38974da6dcdcecc7b4479 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 27 Mar 2024 16:23:51 +0100 Subject: [PATCH 007/100] blueprint: example tree --- .../Core/Geometry/BlueprintNodeTests.cpp | 45 ++++++++++--------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index 0723e8c25b0..986b3bdff90 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -110,6 +110,8 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { } BOOST_AUTO_TEST_CASE(NodeApiTest) { + Transform3 base{AngleAxis3{30_degree, Vector3{1, 0, 0}}}; + auto root = std::make_unique( "root", BinningValue::binZ, CylinderVolumeStack::AttachmentStrategy::Gap, CylinderVolumeStack::ResizeStrategy::Gap); @@ -119,62 +121,63 @@ BOOST_AUTO_TEST_CASE(NodeApiTest) { .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); // cyl->addStaticVolume(std::make_unique( - // Transform3::Identity() * Translation3{Vector3{0, 0, -600_mm}}, + // base * Translation3{Vector3{0, 0, -600_mm}}, // std::make_shared(200_mm, 400_mm, 200_mm), // "PixelNegativeEndcap")); - cyl->addCylinderContainer("PixelNegativeEndcap", binZ, [](auto ec) { + // cyl->addStaticVolume(std::make_unique( + // base * Translation3{Vector3{0, 0, 600_mm}}, + // std::make_shared(200_mm, 400_mm, 200_mm), + // "PixelPositiveEndcap")); + + // cyl->addStaticVolume(std::make_unique( + // base * Translation3{Vector3{0, 0, 0_mm}}, + // std::make_shared(100_mm, 600_mm, 200_mm), + // "PixelBarrel")); + + cyl->addCylinderContainer("PixelNegativeEndcap", binZ, [&](auto ec) { ec->setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap); ec->addStaticVolume(std::make_unique( - Transform3::Identity() * Translation3{Vector3{0, 0, -600_mm}}, + base * Translation3{Vector3{0, 0, -600_mm}}, std::make_shared(200_mm, 450_mm, 20_mm), "PixelNeg1")); ec->addStaticVolume(std::make_unique( - Transform3::Identity() * Translation3{Vector3{0, 0, -400_mm}}, + base * Translation3{Vector3{0, 0, -400_mm}}, std::make_shared(200_mm, 800_mm, 20_mm), - "PixelNeg1")); + "PixelNeg2")); return ec; }); - // cyl->addStaticVolume(std::make_unique( - // Transform3::Identity() * Translation3{Vector3{0, 0, 0_mm}}, - // std::make_shared(100_mm, 600_mm, 200_mm), - // "PixelBarrel")); - - cyl->addCylinderContainer("PixelBarrel", binR, [](auto brl) { + cyl->addCylinderContainer("PixelBarrel", binR, [&](auto brl) { brl->setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Expand); brl->addStaticVolume(std::make_unique( - Transform3::Identity(), - std::make_shared(23_mm, 48_mm, 200_mm), + base, std::make_shared(23_mm, 48_mm, 200_mm), "PixelLayer0")); brl->addStaticVolume(std::make_unique( - Transform3::Identity(), - std::make_shared(87_mm, 103_mm, 250_mm), + base, std::make_shared(87_mm, 103_mm, 250_mm), "PixelLayer1")); brl->addStaticVolume(std::make_unique( - Transform3::Identity(), - std::make_shared(150_mm, 180_mm, 310_mm), + base, std::make_shared(150_mm, 180_mm, 310_mm), "PixelLayer2")); brl->addStaticVolume(std::make_unique( - Transform3::Identity(), - std::make_shared(250_mm, 400_mm, 310_mm), + base, std::make_shared(250_mm, 400_mm, 310_mm), "PixelLayer2")); return brl; }); - cyl->addCylinderContainer("PixelPoxWrapper", binR, [](auto ec) { + cyl->addCylinderContainer("PixelPosWrapper", binR, [&](auto ec) { ec->setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); ec->addStaticVolume(std::make_unique( - Transform3::Identity() * Translation3{Vector3{0, 0, 600_mm}}, + base * Translation3{Vector3{0, 0, 600_mm}}, std::make_shared(150_mm, 390_mm, 200_mm), "PixelPositiveEndcap")); return ec; From 0574a072b17322096cd22f8b59dec52eedbafb98 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Thu, 28 Mar 2024 16:54:58 +0100 Subject: [PATCH 008/100] blueprint: api exploration --- Core/include/Acts/Geometry/BlueprintNode.hpp | 30 +- .../CylinderContainerBlueprintNode.hpp | 10 + .../MaterialDesignatorBlueprintNode.hpp | 56 ++++ .../Acts/Geometry/StaticBlueprintNode.hpp | 3 + Core/src/Geometry/BlueprintNode.cpp | 69 ++++- .../CylinderContainerBlueprintNode.cpp | 2 + Core/src/Geometry/StaticBlueprintNode.cpp | 5 + Examples/Python/CMakeLists.txt | 1 + Examples/Python/src/Blueprint.cpp | 272 ++++++++++++++++++ Examples/Python/src/Geometry.cpp | 5 + Examples/Scripts/Python/blueprint.py | 91 ++++++ .../Core/Geometry/BlueprintNodeTests.cpp | 128 ++++----- 12 files changed, 587 insertions(+), 85 deletions(-) create mode 100644 Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp create mode 100644 Examples/Python/src/Blueprint.cpp create mode 100755 Examples/Scripts/Python/blueprint.py diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index ca158b78a4b..39c3ffff0c6 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -24,6 +24,8 @@ class Volume; class TrackingVolume; class IVisualization3D; class CylinderContainerBlueprintNode; +class MaterialDesignatorBlueprintNode; +class StaticBlueprintNode; class BlueprintNode { public: @@ -44,34 +46,46 @@ class BlueprintNode { virtual void visualize(IVisualization3D& vis, const GeometryContext& gctx) const; - void addStaticVolume(std::unique_ptr volume); + StaticBlueprintNode& addStaticVolume( + std::unique_ptr volume, + const std::function& callback = {}); - void addCylinderContainer( + CylinderContainerBlueprintNode& addCylinderContainer( const std::string& name, BinningValue direction, - const std::function( - std::unique_ptr cylinder)>& factory); + const std::function& + callback = {}); - void addChild(std::unique_ptr child); + MaterialDesignatorBlueprintNode& addMaterial( + const std::function& + callback = {}); + + BlueprintNode& addChild(std::shared_ptr child); using MutableChildRange = detail::TransformRange>>; + std::vector>>; using ChildRange = detail::TransformRange>>; + const std::vector>>; MutableChildRange children(); ChildRange children() const; std::size_t depth() const; + void graphviz(std::ostream& os) const; + protected: std::string prefix() const; + std::string indent() const; + + // Internal method to append to an existing graphviz output stream + virtual void addToGraphviz(std::ostream& os) const; private: std::size_t m_depth{0}; - std::vector> m_children{}; + std::vector> m_children{}; }; }; // namespace Acts diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index 66a2ce475a1..eee67d52458 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -26,6 +26,8 @@ class CylinderContainerBlueprintNode : public BlueprintNode { const std::string& name() const override; + void setName(const std::string& name) { m_name = name; } + Volume& build(const Logger& logger = Acts::getDummyLogger()) override; void connect(TrackingVolume& parent, @@ -40,6 +42,14 @@ class CylinderContainerBlueprintNode : public BlueprintNode { CylinderContainerBlueprintNode& setResizeStrategy( CylinderVolumeStack::ResizeStrategy resizeStrategy); + BinningValue direction() const { return m_direction; } + CylinderVolumeStack::AttachmentStrategy attachmentStrategy() const { + return m_attachmentStrategy; + } + CylinderVolumeStack::ResizeStrategy resizeStrategy() const { + return m_resizeStrategy; + } + private: std::string m_name; diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp new file mode 100644 index 00000000000..39cbf5d0c87 --- /dev/null +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -0,0 +1,56 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Geometry/BlueprintNode.hpp" +namespace Acts { + +class MaterialDesignatorBlueprintNode : public BlueprintNode { + public: + const std::string& name() const override { + const static std::string s_name = "Material"; + return s_name; + } + + void toStream(std::ostream& os) const override { + os << "MaterialDesignatorBlueprintNode(" << name() << ")"; + } + + Volume& build(const Logger& logger = Acts::getDummyLogger()) override { + if (children().size() != 1) { + throw std::runtime_error( + "MaterialDesignatorBlueprintNode must have exactly one child"); + } + return children().at(0).build(logger); + } + + void connect(TrackingVolume& parent, + const Logger& logger = Acts::getDummyLogger()) override { + if (children().size() != 1) { + throw std::runtime_error( + "MaterialDesignatorBlueprintNode must have exactly one child"); + } + children().at(0).connect(parent, logger); + } + + void visualize(IVisualization3D& vis, + const GeometryContext& gctx) const override { + if (children().size() != 1) { + throw std::runtime_error( + "MaterialDesignatorBlueprintNode must have exactly one child"); + } + children().at(0).visualize(vis, gctx); + } + + private: + std::string m_name; + std::string m_material; +}; + +} // namespace Acts diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index 2bfae3c2e69..9ddd90a9b3f 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -35,6 +35,9 @@ class StaticBlueprintNode : public BlueprintNode { return std::move(m_volume); } + // protected: + // void addToGraphviz(std::ostream& os) const override; + private: std::unique_ptr m_volume; }; diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index 512b9156bb9..33a4a3a1f8b 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -9,6 +9,7 @@ #include "Acts/Geometry/BlueprintNode.hpp" #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" +#include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include @@ -16,12 +17,13 @@ namespace Acts { void BlueprintNode::toStream(std::ostream& os) const { - os << "BlueprintNode( " << name() << ")"; + os << "BlueprintNode(" << name() << ")"; } -void BlueprintNode::addChild(std::unique_ptr child) { +BlueprintNode& BlueprintNode::addChild(std::shared_ptr child) { child->m_depth = m_depth + 1; m_children.push_back(std::move(child)); + return *this; } BlueprintNode::MutableChildRange BlueprintNode::children() { @@ -36,8 +38,12 @@ std::size_t BlueprintNode::depth() const { return m_depth; } +std::string BlueprintNode::indent() const { + return std::string(m_depth * 2, ' '); +} + std::string BlueprintNode::prefix() const { - return std::string(m_depth * 2, ' ') + "[" + name() + "]: "; + return indent() + "[" + name() + "]: "; } void BlueprintNode::visualize(IVisualization3D& vis, @@ -47,21 +53,58 @@ void BlueprintNode::visualize(IVisualization3D& vis, } } -void BlueprintNode::addStaticVolume(std::unique_ptr volume) { - addChild(std::make_unique(std::move(volume))); +StaticBlueprintNode& BlueprintNode::addStaticVolume( + std::unique_ptr volume, + const std::function& callback) { + if (!volume) { + throw std::invalid_argument("Volume is nullptr"); + } + + auto child = std::make_shared(std::move(volume)); + addChild(child); + + if (callback) { + callback(*child); + } + return *child; } -void BlueprintNode::addCylinderContainer( +CylinderContainerBlueprintNode& BlueprintNode::addCylinderContainer( const std::string& name, BinningValue direction, - const std::function( - std::unique_ptr cylinder)>& factory) { + const std::function& + callback) { auto cylinder = - std::make_unique(name, direction); - auto node = factory(std::move(cylinder)); - if (!node) { - throw std::runtime_error("Factory did not return a node"); + std::make_shared(name, direction); + addChild(cylinder); + if (callback) { + callback(*cylinder); + } + return *cylinder; +} + +MaterialDesignatorBlueprintNode& BlueprintNode::addMaterial( + const std::function& + callback) { + auto material = std::make_shared(); + addChild(material); + if (callback) { + callback(*material); + } + return *material; +} + +void BlueprintNode::graphviz(std::ostream& os) const { + os << "digraph BlueprintNode {" << std::endl; + addToGraphviz(os); + os << "}" << std::endl; +} + +void BlueprintNode::addToGraphviz(std::ostream& os) const { + for (const auto& child : children()) { + os << indent() << "\"" << name() << "\" -> \"" << child.name() << "\";" + << std::endl; + child.addToGraphviz(os); } - addChild(std::move(node)); } } // namespace Acts diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index fcfa9d2c956..8c19b1333df 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -46,6 +46,8 @@ Volume& CylinderContainerBlueprintNode::build(const Logger& logger) { m_resizeStrategy, logger); ACTS_DEBUG(prefix() << "-> Stack bounds are: " << m_stack->volumeBounds()); + ACTS_DEBUG(prefix() << " *** build complete ***"); + return m_stack.value(); } diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index cff0fdbdfd6..24a5f532d35 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -57,6 +57,9 @@ void StaticBlueprintNode::visualize(IVisualization3D& vis, throw std::runtime_error("Volume is not built"); } + std::cout << "Visualizing StaticBlueprintNode " << name() << std::endl; + std::cout << (*m_volume) << std::endl; + ViewConfig viewConfig{{100, 100, 100}}; GeometryView3D::drawVolume(vis, *m_volume, gctx, Transform3::Identity(), @@ -68,4 +71,6 @@ const std::string& StaticBlueprintNode::name() const { return m_volume->volumeName(); } +// void StaticBlueprintNode::addToGraphviz(std::ostream& os) const {} + } // namespace Acts diff --git a/Examples/Python/CMakeLists.txt b/Examples/Python/CMakeLists.txt index 0eb4b1ff4ec..237a7915838 100644 --- a/Examples/Python/CMakeLists.txt +++ b/Examples/Python/CMakeLists.txt @@ -16,6 +16,7 @@ pybind11_add_module(ActsPythonBindings src/Material.cpp src/Geometry.cpp src/GeometryBuildingGen1.cpp + src/Blueprint.cpp src/ExampleAlgorithms.cpp src/MagneticField.cpp src/Output.cpp diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp new file mode 100644 index 00000000000..70491f11e37 --- /dev/null +++ b/Examples/Python/src/Blueprint.cpp @@ -0,0 +1,272 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Geometry/BlueprintNode.hpp" +#include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" +#include "Acts/Geometry/CylinderVolumeStack.hpp" +#include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" +#include "Acts/Geometry/StaticBlueprintNode.hpp" +#include "Acts/Plugins/Python/Utilities.hpp" +#include "Acts/Utilities/BinningType.hpp" +#include "Acts/Utilities/Logger.hpp" + +#include +#include +#include + +namespace py = pybind11; +using namespace pybind11::literals; + +namespace Acts::Python { +void addBlueprint(Context& ctx) { + auto m = ctx.get("main"); + + struct AddCylinderContainerHelper { + BlueprintNode& parent; + BinningValue direction; + std::optional name; + + std::shared_ptr operator()( + py::function callback) { + auto cylinder = std::make_shared( + name.value_or(callback.attr("__name__").cast()), + direction); + parent.addChild(cylinder); + callback(cylinder); + return cylinder; + } + + std::shared_ptr enter() { + if (!name.has_value()) { + throw std::invalid_argument("Name is required in context manager"); + } + auto cylinder = std::make_shared( + name.value(), direction); + parent.addChild(cylinder); + return cylinder; + } + + void exit(py::object, py::object, py::object) {} + }; + + py::class_(m, "_AddCylinderContainerHelper") + .def("__call__", &AddCylinderContainerHelper::operator()) + .def("__enter__", &AddCylinderContainerHelper::enter) + .def("__exit__", &AddCylinderContainerHelper::exit); + + struct AddMaterialDesignatorHelper { + BlueprintNode& parent; + + std::shared_ptr operator()(py::function callback) { + auto material = std::make_shared(); + parent.addChild(material); + callback(material); + return material; + } + + std::shared_ptr enter() { + auto material = std::make_shared(); + parent.addChild(material); + return material; + } + + void exit(py::object, py::object, py::object) {} + }; + + py::class_(m, "_AddMaterialDesignatorHelper") + .def("__call__", &AddMaterialDesignatorHelper::operator()) + .def("__enter__", &AddMaterialDesignatorHelper::enter) + .def("__exit__", &AddMaterialDesignatorHelper::exit); + + struct AddStaticVolumeHelper { + BlueprintNode& parent; + Transform3 transform; + std::shared_ptr bounds; + std::optional name; + + std::shared_ptr operator()(py::function callback) { + std::string callbackName = callback.attr("__name__").cast(); + auto node = std::make_shared( + std::make_unique(transform, bounds, + name.value_or(callbackName))); + parent.addChild(node); + callback(node); + return node; + } + + std::shared_ptr enter() { + if (!name.has_value()) { + throw std::invalid_argument("Name is required in context manager"); + } + auto node = std::make_shared( + std::make_unique(transform, bounds, + name.value())); + parent.addChild(node); + return node; + } + + void exit(py::object, py::object, py::object) {} + }; + + py::class_(m, "_AddStaticVolumeHelper") + .def("__call__", &AddStaticVolumeHelper::operator()) + .def("__enter__", &AddStaticVolumeHelper::enter) + .def("__exit__", &AddStaticVolumeHelper::exit); + + auto blueprintNode = + py::class_>(m, + "BlueprintNode") + .def("__str__", + [](const BlueprintNode& self) { + std::stringstream ss; + self.toStream(ss); + return ss.str(); + }) + .def( + "addStaticVolume", + [](BlueprintNode& self, const Transform3& transform, + std::shared_ptr bounds, + const std::string& name) { + auto node = std::make_shared( + std::make_unique(transform, bounds, + name)); + self.addChild(node); + return node; + }, + py::arg("transform"), py::arg("bounds"), + py::arg("name") = "undefined") + + .def( + "StaticVolume", + [](BlueprintNode& self, const Transform3& transform, + std::shared_ptr bounds, + std::optional name = std::nullopt) { + return AddStaticVolumeHelper{self, transform, bounds, + name.value_or("undefined")}; + }, + py::arg("transform"), py::arg("bounds"), + py::arg("name") = std::nullopt) + + .def( + "addCylinderContainer", + [](BlueprintNode& self, const std::string& name, + BinningValue direction) { + auto cylinder = + std::make_shared(name, + direction); + self.addChild(cylinder); + return cylinder; + }, + py::arg("name"), py::arg("direction")) + + .def( + "CylinderContainer", + [](BlueprintNode& self, BinningValue direction, + std::optional name = std::nullopt) { + return AddCylinderContainerHelper{self, direction, name}; + }, + py::arg("direction"), py::arg("name") = std::nullopt) + + .def("Material", + [](BlueprintNode& self) { + return AddMaterialDesignatorHelper{self}; + }) + + .def("addChild", &BlueprintNode::addChild) + .def_property_readonly("children", + py::overload_cast<>(&BlueprintNode::children)) + .def_property_readonly("name", &BlueprintNode::name) + .def("graphviz", + [](BlueprintNode& self, py::object fh) { + std::stringstream ss; + self.graphviz(ss); + fh.attr("write")(ss.str()); + }) + .def("visualize", &BlueprintNode::visualize) + .def( + "build", + [](BlueprintNode& self, Logging::Level level) { + return self.build(*getDefaultLogger("Blueprint", level)); + }, + py::arg("level") = Logging::INFO); + + py::class_(blueprintNode, + "MutableChildRange") + .def( + "__iter__", + [](BlueprintNode::MutableChildRange& self) { + return py::make_iterator(self.begin(), self.end()); + }, + py::keep_alive<0, 1>()) + .def( + "__getitem__", + [](BlueprintNode::MutableChildRange& self, + int i) -> Acts::BlueprintNode& { + if (i < 0) { + i += self.size(); + } + return self.at(i); + }, + py::return_value_policy::reference_internal) + .def("__len__", [](const BlueprintNode::MutableChildRange& self) { + return self.size(); + }); + + py::class_>(m, + "StaticBlueprintNode") + .def(py::init([](const Transform3& transform, + std::shared_ptr bounds, + const std::string& name) { + return std::make_shared( + std::make_unique(transform, bounds, + name)); + }), + py::arg("transform"), py::arg("bounds"), + py::arg("name") = "undefined"); + + auto cylNode = + py::class_>( + m, "CylinderContainerBlueprintNode") + .def(py::init(), + py::arg("name"), py::arg("direction"), + py::arg("attachmentStrategy") = + CylinderVolumeStack::AttachmentStrategy::Gap, + py::arg("resizeStrategy") = + CylinderVolumeStack::ResizeStrategy::Gap) + .def_property( + "attachmentStrategy", + [](Acts::CylinderContainerBlueprintNode& self) { + return self.attachmentStrategy(); + }, + [](Acts::CylinderContainerBlueprintNode& self, + CylinderVolumeStack::AttachmentStrategy strategy) { + self.setAttachmentStrategy(strategy); + }) + .def_property( + "resizeStrategy", + [](Acts::CylinderContainerBlueprintNode& self) { + return self.resizeStrategy(); + }, + [](Acts::CylinderContainerBlueprintNode& self, + CylinderVolumeStack::ResizeStrategy strategy) { + self.setResizeStrategy(strategy); + }) + .def_property( + "direction", + [](Acts::CylinderContainerBlueprintNode& self) { + return self.direction(); + }, + [](Acts::CylinderContainerBlueprintNode& self, + BinningValue value) { self.setDirection(value); }); +} + +} // namespace Acts::Python diff --git a/Examples/Python/src/Geometry.cpp b/Examples/Python/src/Geometry.cpp index 4c15e0dcf94..2d5ef4e8994 100644 --- a/Examples/Python/src/Geometry.cpp +++ b/Examples/Python/src/Geometry.cpp @@ -91,6 +91,9 @@ struct IdentifierSurfacesCollector { } // namespace namespace Acts::Python { + +void addBlueprint(Context& ctx); + void addGeometry(Context& ctx) { auto m = ctx.get("main"); @@ -301,6 +304,8 @@ void addGeometry(Context& ctx) { .value("Gap", CylinderVolumeStack::ResizeStrategy::Gap) .value("Expand", CylinderVolumeStack::ResizeStrategy::Expand); } + + addBlueprint(ctx); } void addExperimentalGeometry(Context& ctx) { diff --git a/Examples/Scripts/Python/blueprint.py b/Examples/Scripts/Python/blueprint.py new file mode 100755 index 00000000000..3da23a9723b --- /dev/null +++ b/Examples/Scripts/Python/blueprint.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 + +import acts + +mm = acts.UnitConstants.mm +degree = acts.UnitConstants.degree + +root = acts.CylinderContainerBlueprintNode("root", acts.BinningValue.binR) + +pixel = root.addCylinderContainer(direction=acts.BinningValue.binZ, name="Pixel") +print(repr(pixel)) + +trf = acts.Transform3.Identity() * acts.Translation3(acts.Vector3(0, 0, 0 * mm)) + + +barrel = acts.CylinderContainerBlueprintNode( + "PixelBarrel", + acts.BinningValue.binR, + attachmentStrategy=acts.CylinderVolumeStack.AttachmentStrategy.Gap, +) +pixel.addChild(barrel) + +print("Barrel") +r = 25 * mm +for i in range(0, 4): + r += 50 * mm + bounds = acts.CylinderVolumeBounds(r, r + 20 * mm, 200 * mm) + print(bounds) + brlLayer = barrel.addStaticVolume(trf, bounds, name=f"PixelBarrelLayer{i}") + assert brlLayer.name == f"PixelBarrelLayer{i}" + + +if True: + + @pixel.CylinderContainer(acts.BinningValue.binZ) + def PixelPosEndcap(ec): + print("Positive Endcap") + + ec.attachmentStrategy = acts.CylinderVolumeStack.AttachmentStrategy.Gap + ec.resizeStrategy = acts.CylinderVolumeStack.ResizeStrategy.Gap + + z = 200 + for i in range(0, 4): + z += 200 * mm + bounds = acts.CylinderVolumeBounds(100 * mm, 150 * mm, 50 * mm) + print(bounds) + + trf = acts.Transform3.Identity() * acts.Translation3(acts.Vector3(0, 0, z)) + + @ec.StaticVolume(trf, bounds, name=f"PixelPosEndcapDisk{i}") + def PixelEndcapDisk(disk): + print("Add disk", i) + + assert PixelEndcapDisk.name == f"PixelPosEndcapDisk{i}" + + +if False: + with pixel.Material() as mat: + with mat.CylinderContainer(acts.BinningValue.binZ, name="PixelNegEndcap") as ec: + ec.attachmentStrategy = acts.CylinderVolumeStack.AttachmentStrategy.Gap + + print("Negative Endcap") + + z = -200 + for i in range(0, 4): + z -= 200 * mm + bounds = acts.CylinderVolumeBounds(200 * mm, 300 * mm, 50 * mm) + print(bounds) + + trf = acts.Transform3.Identity() * acts.Translation3( + acts.Vector3(0, 0, z) + ) + + with ec.StaticVolume( + trf, bounds, name=f"PixelNegEndcapDisk{i}" + ) as disk: + print("Add disk", i) + assert disk.name == f"PixelNegEndcapDisk{i}" + + +with open("blueprint.dot", "w") as fh: + root.graphviz(fh) + +vis = acts.ObjVisualization3D() + +root.build(level=acts.logging.VERBOSE) + +gctx = acts.GeometryContext() +root.visualize(vis, gctx) + +vis.write("blueprint.obj") diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index 986b3bdff90..3ccd48d31ef 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -15,6 +15,7 @@ #include "Acts/Definitions/Units.hpp" #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Geometry/TrackingVolume.hpp" #include "Acts/Utilities/Logger.hpp" @@ -116,80 +117,79 @@ BOOST_AUTO_TEST_CASE(NodeApiTest) { "root", BinningValue::binZ, CylinderVolumeStack::AttachmentStrategy::Gap, CylinderVolumeStack::ResizeStrategy::Gap); - root->addCylinderContainer("Pixel", binZ, [&](auto cyl) { - cyl->setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) - .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); - - // cyl->addStaticVolume(std::make_unique( - // base * Translation3{Vector3{0, 0, -600_mm}}, - // std::make_shared(200_mm, 400_mm, 200_mm), - // "PixelNegativeEndcap")); - - // cyl->addStaticVolume(std::make_unique( - // base * Translation3{Vector3{0, 0, 600_mm}}, - // std::make_shared(200_mm, 400_mm, 200_mm), - // "PixelPositiveEndcap")); - - // cyl->addStaticVolume(std::make_unique( - // base * Translation3{Vector3{0, 0, 0_mm}}, - // std::make_shared(100_mm, 600_mm, 200_mm), - // "PixelBarrel")); - - cyl->addCylinderContainer("PixelNegativeEndcap", binZ, [&](auto ec) { - ec->setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap); - - ec->addStaticVolume(std::make_unique( - base * Translation3{Vector3{0, 0, -600_mm}}, - std::make_shared(200_mm, 450_mm, 20_mm), - "PixelNeg1")); - - ec->addStaticVolume(std::make_unique( - base * Translation3{Vector3{0, 0, -400_mm}}, - std::make_shared(200_mm, 800_mm, 20_mm), - "PixelNeg2")); - - return ec; - }); - - cyl->addCylinderContainer("PixelBarrel", binR, [&](auto brl) { - brl->setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) - .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Expand); - - brl->addStaticVolume(std::make_unique( - base, std::make_shared(23_mm, 48_mm, 200_mm), - "PixelLayer0")); - - brl->addStaticVolume(std::make_unique( - base, std::make_shared(87_mm, 103_mm, 250_mm), - "PixelLayer1")); - - brl->addStaticVolume(std::make_unique( - base, std::make_shared(150_mm, 180_mm, 310_mm), - "PixelLayer2")); - - brl->addStaticVolume(std::make_unique( - base, std::make_shared(250_mm, 400_mm, 310_mm), - "PixelLayer2")); - - return brl; - }); - - cyl->addCylinderContainer("PixelPosWrapper", binR, [&](auto ec) { - ec->setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); - ec->addStaticVolume(std::make_unique( + root->addMaterial([&](auto& mat) { + mat.addCylinderContainer("Pixel", binZ, [&](auto& cyl) { + cyl.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) + .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); + + // cyl->addStaticVolume(std::make_unique( + // base * Translation3{Vector3{0, 0, -600_mm}}, + // std::make_shared(200_mm, 400_mm, 200_mm), + // "PixelNegativeEndcap")); + + // cyl->addStaticVolume(std::make_unique( + // base * Translation3{Vector3{0, 0, 600_mm}}, + // std::make_shared(200_mm, 400_mm, 200_mm), + // "PixelPositiveEndcap")); + + // cyl->addStaticVolume(std::make_unique( + // base * Translation3{Vector3{0, 0, 0_mm}}, + // std::make_shared(100_mm, 600_mm, 200_mm), + // "PixelBarrel")); + + cyl.addCylinderContainer("PixelNegativeEndcap", binZ, [&](auto& ec) { + ec.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap); + + ec.addStaticVolume(std::make_unique( + base * Translation3{Vector3{0, 0, -600_mm}}, + std::make_shared(200_mm, 450_mm, 20_mm), + "PixelNeg1")); + + ec.addStaticVolume(std::make_unique( + base * Translation3{Vector3{0, 0, -400_mm}}, + std::make_shared(200_mm, 800_mm, 20_mm), + "PixelNeg2")); + }); + + cyl.addCylinderContainer("PixelBarrel", binR, [&](auto& brl) { + brl.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) + .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Expand); + + brl.addStaticVolume(std::make_unique( + base, std::make_shared(23_mm, 48_mm, 200_mm), + "PixelLayer0")); + + brl.addStaticVolume(std::make_unique( + base, std::make_shared(87_mm, 103_mm, 250_mm), + "PixelLayer1")); + + brl.addStaticVolume(std::make_unique( + base, + std::make_shared(150_mm, 180_mm, 310_mm), + "PixelLayer2")); + + brl.addStaticVolume(std::make_unique( + base, + std::make_shared(250_mm, 400_mm, 310_mm), + "PixelLayer3")); + }); + + auto& ec = cyl.addCylinderContainer("PixelPosWrapper", binR); + ec.setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); + ec.addStaticVolume(std::make_unique( base * Translation3{Vector3{0, 0, 600_mm}}, std::make_shared(150_mm, 390_mm, 200_mm), "PixelPositiveEndcap")); - return ec; }); - - return cyl; }); auto world = root->build(*logger); ObjVisualization3D vis; root->visualize(vis, gctx); vis.write("api_test.obj"); + + std::ofstream dot{"api_test.dot"}; + root->graphviz(dot); } BOOST_AUTO_TEST_SUITE_END(); From e149a82a4df68b3526c08a7dbfa1395349fb316b Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 8 Apr 2024 12:01:07 +0200 Subject: [PATCH 009/100] blueprint: api in parts --- Examples/Scripts/Python/blueprint.py | 34 +++++++++++++++------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/Examples/Scripts/Python/blueprint.py b/Examples/Scripts/Python/blueprint.py index 3da23a9723b..b63f5fe86ec 100755 --- a/Examples/Scripts/Python/blueprint.py +++ b/Examples/Scripts/Python/blueprint.py @@ -13,21 +13,23 @@ trf = acts.Transform3.Identity() * acts.Translation3(acts.Vector3(0, 0, 0 * mm)) -barrel = acts.CylinderContainerBlueprintNode( - "PixelBarrel", - acts.BinningValue.binR, - attachmentStrategy=acts.CylinderVolumeStack.AttachmentStrategy.Gap, -) -pixel.addChild(barrel) - -print("Barrel") -r = 25 * mm -for i in range(0, 4): - r += 50 * mm - bounds = acts.CylinderVolumeBounds(r, r + 20 * mm, 200 * mm) - print(bounds) - brlLayer = barrel.addStaticVolume(trf, bounds, name=f"PixelBarrelLayer{i}") - assert brlLayer.name == f"PixelBarrelLayer{i}" +if True: + barrel = acts.CylinderContainerBlueprintNode( + "PixelBarrel", + acts.BinningValue.binR, + attachmentStrategy=acts.CylinderVolumeStack.AttachmentStrategy.Gap, + resizeStrategy=acts.CylinderVolumeStack.ResizeStrategy.Gap, + ) + pixel.addChild(barrel) + + print("Barrel") + r = 25 * mm + for i in range(0, 4): + r += 50 * mm + bounds = acts.CylinderVolumeBounds(r, r + 20 * mm, 200 * mm) + print(bounds) + brlLayer = barrel.addStaticVolume(trf, bounds, name=f"PixelBarrelLayer{i}") + assert brlLayer.name == f"PixelBarrelLayer{i}" if True: @@ -54,7 +56,7 @@ def PixelEndcapDisk(disk): assert PixelEndcapDisk.name == f"PixelPosEndcapDisk{i}" -if False: +if True: with pixel.Material() as mat: with mat.CylinderContainer(acts.BinningValue.binZ, name="PixelNegEndcap") as ec: ec.attachmentStrategy = acts.CylinderVolumeStack.AttachmentStrategy.Gap From 57874a2329d74b513926d3a13c08e88287d6ff82 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 5 Jun 2024 11:13:22 +0200 Subject: [PATCH 010/100] blueprint: add missing headers --- Core/include/Acts/Geometry/Blueprint.hpp | 27 ++++++++++++++++++++++++ Core/src/Geometry/Blueprint.cpp | 15 +++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 Core/include/Acts/Geometry/Blueprint.hpp create mode 100644 Core/src/Geometry/Blueprint.cpp diff --git a/Core/include/Acts/Geometry/Blueprint.hpp b/Core/include/Acts/Geometry/Blueprint.hpp new file mode 100644 index 00000000000..2492bb33738 --- /dev/null +++ b/Core/include/Acts/Geometry/Blueprint.hpp @@ -0,0 +1,27 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include + +namespace Acts { + +class TrackingVolume; + +class Blueprint { + std::unique_ptr build(); + + // void setStaticVolume(std::unique_ptr volume); + + // void setCylinderContainer( + // const std::function( + // std::unique_ptr cylinder)>& factory); +}; + +} // namespace Acts diff --git a/Core/src/Geometry/Blueprint.cpp b/Core/src/Geometry/Blueprint.cpp new file mode 100644 index 00000000000..5cb6a54efd0 --- /dev/null +++ b/Core/src/Geometry/Blueprint.cpp @@ -0,0 +1,15 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Geometry/Blueprint.hpp" + +namespace Acts { + +std::unique_ptr Blueprint::build() {} + +} // namespace Acts From c3e63503790e7f110205036eea655ec37a3c78f1 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 9 Aug 2024 12:20:35 +0200 Subject: [PATCH 011/100] blueprint: fix to blueprintnode after BinningValueChange --- .../Core/Geometry/BlueprintNodeTests.cpp | 85 ++++++++++--------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index 3ccd48d31ef..618fb3241c2 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(NodeApiTest) { CylinderVolumeStack::ResizeStrategy::Gap); root->addMaterial([&](auto& mat) { - mat.addCylinderContainer("Pixel", binZ, [&](auto& cyl) { + mat.addCylinderContainer("Pixel", BinningValue::binZ, [&](auto& cyl) { cyl.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); @@ -137,44 +137,51 @@ BOOST_AUTO_TEST_CASE(NodeApiTest) { // std::make_shared(100_mm, 600_mm, 200_mm), // "PixelBarrel")); - cyl.addCylinderContainer("PixelNegativeEndcap", binZ, [&](auto& ec) { - ec.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap); - - ec.addStaticVolume(std::make_unique( - base * Translation3{Vector3{0, 0, -600_mm}}, - std::make_shared(200_mm, 450_mm, 20_mm), - "PixelNeg1")); - - ec.addStaticVolume(std::make_unique( - base * Translation3{Vector3{0, 0, -400_mm}}, - std::make_shared(200_mm, 800_mm, 20_mm), - "PixelNeg2")); - }); - - cyl.addCylinderContainer("PixelBarrel", binR, [&](auto& brl) { - brl.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) - .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Expand); - - brl.addStaticVolume(std::make_unique( - base, std::make_shared(23_mm, 48_mm, 200_mm), - "PixelLayer0")); - - brl.addStaticVolume(std::make_unique( - base, std::make_shared(87_mm, 103_mm, 250_mm), - "PixelLayer1")); - - brl.addStaticVolume(std::make_unique( - base, - std::make_shared(150_mm, 180_mm, 310_mm), - "PixelLayer2")); - - brl.addStaticVolume(std::make_unique( - base, - std::make_shared(250_mm, 400_mm, 310_mm), - "PixelLayer3")); - }); - - auto& ec = cyl.addCylinderContainer("PixelPosWrapper", binR); + cyl.addCylinderContainer( + "PixelNegativeEndcap", BinningValue::binZ, [&](auto& ec) { + ec.setAttachmentStrategy( + CylinderVolumeStack::AttachmentStrategy::Gap); + + ec.addStaticVolume(std::make_unique( + base * Translation3{Vector3{0, 0, -600_mm}}, + std::make_shared(200_mm, 450_mm, 20_mm), + "PixelNeg1")); + + ec.addStaticVolume(std::make_unique( + base * Translation3{Vector3{0, 0, -400_mm}}, + std::make_shared(200_mm, 800_mm, 20_mm), + "PixelNeg2")); + }); + + cyl.addCylinderContainer( + "PixelBarrel", BinningValue::binR, [&](auto& brl) { + brl.setAttachmentStrategy( + CylinderVolumeStack::AttachmentStrategy::Gap) + .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Expand); + + brl.addStaticVolume(std::make_unique( + base, + std::make_shared(23_mm, 48_mm, 200_mm), + "PixelLayer0")); + + brl.addStaticVolume(std::make_unique( + base, + std::make_shared(87_mm, 103_mm, 250_mm), + "PixelLayer1")); + + brl.addStaticVolume(std::make_unique( + base, + std::make_shared(150_mm, 180_mm, 310_mm), + "PixelLayer2")); + + brl.addStaticVolume(std::make_unique( + base, + std::make_shared(250_mm, 400_mm, 310_mm), + "PixelLayer3")); + }); + + auto& ec = + cyl.addCylinderContainer("PixelPosWrapper", BinningValue::binR); ec.setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); ec.addStaticVolume(std::make_unique( base * Translation3{Vector3{0, 0, 600_mm}}, From 94ca5451abcfd58c7faf908658a5e867fa338d85 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 9 Aug 2024 12:32:44 +0200 Subject: [PATCH 012/100] blueprint: add missing semicolons --- Core/src/Geometry/StaticBlueprintNode.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index 24a5f532d35..bad8f958581 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -29,7 +29,7 @@ Volume& StaticBlueprintNode::build(const Logger& logger) { void StaticBlueprintNode::connect(TrackingVolume& parent, const Logger& logger) { - ACTS_DEBUG(prefix() << "static connect") + ACTS_DEBUG(prefix() << "static connect"); if (!m_volume) { throw std::runtime_error("Volume is not built"); } @@ -41,7 +41,7 @@ void StaticBlueprintNode::connect(TrackingVolume& parent, } void StaticBlueprintNode::connect(const Logger& logger) { - ACTS_DEBUG(prefix() << "static connect") + ACTS_DEBUG(prefix() << "static connect"); if (!m_volume) { throw std::runtime_error("Volume is not built"); } From 119eb18f72cd6e9efa869406ff3e44fa1dc1afbd Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 27 Aug 2024 18:12:55 +0200 Subject: [PATCH 013/100] blueprint: Experimenting with shell implementation --- Core/include/Acts/Geometry/BlueprintNode.hpp | 16 ++-- .../CylinderContainerBlueprintNode.hpp | 14 +++- .../MaterialDesignatorBlueprintNode.hpp | 15 +++- .../Acts/Geometry/StaticBlueprintNode.hpp | 15 ++-- Core/src/Geometry/BlueprintNode.cpp | 2 +- .../CylinderContainerBlueprintNode.cpp | 45 +++++++++-- Core/src/Geometry/StaticBlueprintNode.cpp | 77 +++++++++++++++---- Examples/Python/src/Blueprint.cpp | 20 +++-- Examples/Scripts/Python/blueprint.py | 2 +- 9 files changed, 151 insertions(+), 55 deletions(-) diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index 39c3ffff0c6..3ebaf98b479 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -22,6 +22,7 @@ namespace Acts { class Volume; class TrackingVolume; +class PortalShellBase; class IVisualization3D; class CylinderContainerBlueprintNode; class MaterialDesignatorBlueprintNode; @@ -39,9 +40,12 @@ class BlueprintNode { virtual Volume& build(const Logger& logger = Acts::getDummyLogger()) = 0; - // @TODO: This should return the portal "shell" - virtual void connect(TrackingVolume& parent, - const Logger& logger = Acts::getDummyLogger()) = 0; + virtual PortalShellBase& connect( + const GeometryContext& gctx, + const Logger& logger = Acts::getDummyLogger()) = 0; + + // virtual void finalize(TrackingVolume& parent, + // const Logger& logger = Acts::getDummyLogger()) = 0; virtual void visualize(IVisualization3D& vis, const GeometryContext& gctx) const; @@ -74,15 +78,13 @@ class BlueprintNode { std::size_t depth() const; - void graphviz(std::ostream& os) const; + void graphViz(std::ostream& os) const; + virtual void addToGraphviz(std::ostream& os) const; protected: std::string prefix() const; std::string indent() const; - // Internal method to append to an existing graphviz output stream - virtual void addToGraphviz(std::ostream& os) const; - private: std::size_t m_depth{0}; std::vector> m_children{}; diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index eee67d52458..aff7bb4d86c 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -10,12 +10,13 @@ #include "Acts/Geometry/BlueprintNode.hpp" #include "Acts/Geometry/CylinderVolumeStack.hpp" +#include "Acts/Geometry/PortalShell.hpp" #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Logger.hpp" namespace Acts { -class CylinderContainerBlueprintNode : public BlueprintNode { +class CylinderContainerBlueprintNode final : public BlueprintNode { public: CylinderContainerBlueprintNode( const std::string& name, BinningValue direction, @@ -30,8 +31,9 @@ class CylinderContainerBlueprintNode : public BlueprintNode { Volume& build(const Logger& logger = Acts::getDummyLogger()) override; - void connect(TrackingVolume& parent, - const Logger& logger = Acts::getDummyLogger()) override; + CylinderStackPortalShell& connect( + const GeometryContext& gctx, + const Logger& logger = Acts::getDummyLogger()) override; void visualize(IVisualization3D& vis, const GeometryContext& gctx) const override; @@ -51,6 +53,8 @@ class CylinderContainerBlueprintNode : public BlueprintNode { } private: + void addToGraphviz(std::ostream& os) const override; + std::string m_name; BinningValue m_direction; @@ -60,6 +64,10 @@ class CylinderContainerBlueprintNode : public BlueprintNode { // Is only initialized during `build` std::vector m_childVolumes; std::optional m_stack{std::nullopt}; + + std::vector> m_gapVolumes; + + std::optional m_shell{std::nullopt}; }; } // namespace Acts diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index 39cbf5d0c87..d73e6507d45 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -9,9 +9,10 @@ #pragma once #include "Acts/Geometry/BlueprintNode.hpp" +#include "Acts/Utilities/GraphViz.hpp" namespace Acts { -class MaterialDesignatorBlueprintNode : public BlueprintNode { +class MaterialDesignatorBlueprintNode final : public BlueprintNode { public: const std::string& name() const override { const static std::string s_name = "Material"; @@ -30,13 +31,14 @@ class MaterialDesignatorBlueprintNode : public BlueprintNode { return children().at(0).build(logger); } - void connect(TrackingVolume& parent, - const Logger& logger = Acts::getDummyLogger()) override { + PortalShellBase& connect( + const GeometryContext& gctx, + const Logger& logger = Acts::getDummyLogger()) override { if (children().size() != 1) { throw std::runtime_error( "MaterialDesignatorBlueprintNode must have exactly one child"); } - children().at(0).connect(parent, logger); + return children().at(0).connect(gctx, logger); } void visualize(IVisualization3D& vis, @@ -48,6 +50,11 @@ class MaterialDesignatorBlueprintNode : public BlueprintNode { children().at(0).visualize(vis, gctx); } + void addToGraphviz(std::ostream& os) const override { + os << GraphViz::Node{.id = name(), .shape = GraphViz::Shape::InvTrapezium}; + BlueprintNode::addToGraphviz(os); + } + private: std::string m_name; std::string m_material; diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index 9ddd90a9b3f..d28acb6c339 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -10,6 +10,7 @@ #include "Acts/Geometry/BlueprintNode.hpp" #include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/PortalShell.hpp" #include "Acts/Geometry/TrackingVolume.hpp" namespace Acts { @@ -22,24 +23,24 @@ class StaticBlueprintNode : public BlueprintNode { Volume& build(const Logger& logger = Acts::getDummyLogger()) override; - void connect(TrackingVolume& parent, - const Logger& logger = Acts::getDummyLogger()) override; + PortalShellBase& connect( + const GeometryContext& gctx, + const Logger& logger = Acts::getDummyLogger()) override; void visualize(IVisualization3D& vis, const GeometryContext& gctx) const override; - // This connects averything to the static volume contained here - void connect(const Logger& logger = Acts::getDummyLogger()); - std::unique_ptr releaseVolume() { return std::move(m_volume); } - // protected: - // void addToGraphviz(std::ostream& os) const override; + protected: + void addToGraphviz(std::ostream& os) const override; private: std::unique_ptr m_volume; + + std::unique_ptr m_shell; }; } // namespace Acts diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index 33a4a3a1f8b..21292571b0b 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -93,7 +93,7 @@ MaterialDesignatorBlueprintNode& BlueprintNode::addMaterial( return *material; } -void BlueprintNode::graphviz(std::ostream& os) const { +void BlueprintNode::graphViz(std::ostream& os) const { os << "digraph BlueprintNode {" << std::endl; addToGraphviz(os); os << "}" << std::endl; diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 8c19b1333df..1ce593a896e 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -9,7 +9,10 @@ #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/BlueprintNode.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/PortalShell.hpp" #include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Utilities/GraphViz.hpp" #include "Acts/Visualization/GeometryView3D.hpp" #include "Acts/Visualization/ViewConfig.hpp" @@ -51,21 +54,37 @@ Volume& CylinderContainerBlueprintNode::build(const Logger& logger) { return m_stack.value(); } -void CylinderContainerBlueprintNode::connect(TrackingVolume& parent, - const Logger& logger) { +CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( + const GeometryContext& gctx, const Logger& logger) { ACTS_DEBUG(prefix() << "cylinder container connect"); if (!m_stack.has_value()) { throw std::runtime_error("Volume is not built"); } + std::vector shells; + ACTS_VERBOSE("Collecting child shells from " << children().size() + << " children"); for (auto& child : children()) { - child.connect(parent); + PortalShellBase& shell = child.connect(gctx, logger); + if (auto* cylShell = dynamic_cast(&shell); + cylShell != nullptr) { + shells.push_back(cylShell); + } else { + throw std::runtime_error("Child volume is not a cylinder"); + } } - for (auto& gap : m_stack->gaps()) { - auto tv = std::make_unique(*gap); - parent.addVolume(std::move(tv)); - } + ACTS_VERBOSE("Producing merged cylinder stack shell in " << m_direction + << " direction"); + m_shell.emplace(gctx, std::move(shells), m_direction, logger); + + return m_shell.value(); + + // This goes into finalize at the end + // for (auto& gap : m_stack->gaps()) { + // auto tv = std::make_unique(*gap); + // parent.addVolume(std::move(tv)); + // } } void CylinderContainerBlueprintNode::visualize( @@ -113,4 +132,16 @@ CylinderContainerBlueprintNode::setResizeStrategy( return *this; } +void CylinderContainerBlueprintNode::addToGraphviz(std::ostream& os) const { + GraphViz::Node node{.id = name(), + .label = "" + name() + "
Cylinder", + .shape = GraphViz::Shape::Folder}; + os << node << std::endl; + for (const auto& child : children()) { + os << indent() << GraphViz::Edge{{.id = name()}, {.id = child.name()}} + << std::endl; + child.addToGraphviz(os); + } +} + } // namespace Acts diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index bad8f958581..9a69047a740 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -9,6 +9,9 @@ #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/PortalShell.hpp" +#include "Acts/Geometry/VolumeBounds.hpp" +#include "Acts/Utilities/GraphViz.hpp" #include "Acts/Visualization/GeometryView3D.hpp" #include "Acts/Visualization/ViewConfig.hpp" @@ -27,28 +30,34 @@ Volume& StaticBlueprintNode::build(const Logger& logger) { return *m_volume; } -void StaticBlueprintNode::connect(TrackingVolume& parent, - const Logger& logger) { +PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, + const Logger& logger) { ACTS_DEBUG(prefix() << "static connect"); - if (!m_volume) { + if (m_volume == nullptr) { throw std::runtime_error("Volume is not built"); } + ACTS_VERBOSE("Connecting parent volume (" + << name() << ") with " << children().size() << " children"); + for (auto& child : children()) { - child.connect(*m_volume); + auto& shell = child.connect(gctx, logger); + // Register ourselves on the outside of the shell + shell.connectOuter(*m_volume); } - parent.addVolume(std::move(m_volume)); -} -void StaticBlueprintNode::connect(const Logger& logger) { - ACTS_DEBUG(prefix() << "static connect"); - if (!m_volume) { - throw std::runtime_error("Volume is not built"); - } + VolumeBounds::BoundsType type = m_volume->volumeBounds().type(); + if (type == VolumeBounds::eCylinder) { + m_shell = std::make_unique(*m_volume); - for (auto& child : children()) { - child.connect(*m_volume); + } else if (type == VolumeBounds::eCuboid) { + throw std::logic_error("Cuboid is not implemented yet"); + + } else { + throw std::logic_error("Volume type is not supported"); } + + return *m_shell; } void StaticBlueprintNode::visualize(IVisualization3D& vis, @@ -57,9 +66,6 @@ void StaticBlueprintNode::visualize(IVisualization3D& vis, throw std::runtime_error("Volume is not built"); } - std::cout << "Visualizing StaticBlueprintNode " << name() << std::endl; - std::cout << (*m_volume) << std::endl; - ViewConfig viewConfig{{100, 100, 100}}; GeometryView3D::drawVolume(vis, *m_volume, gctx, Transform3::Identity(), @@ -68,9 +74,46 @@ void StaticBlueprintNode::visualize(IVisualization3D& vis, } const std::string& StaticBlueprintNode::name() const { + static const std::string uninitialized = "uninitialized"; + if (m_volume == nullptr) { + return uninitialized; + } return m_volume->volumeName(); } -// void StaticBlueprintNode::addToGraphviz(std::ostream& os) const {} +void StaticBlueprintNode::addToGraphviz(std::ostream& os) const { + std::stringstream ss; + ss << "" << name() << ""; + ss << "
"; + switch (m_volume->volumeBounds().type()) { + case VolumeBounds::eCylinder: + ss << "Cylinder"; + break; + case VolumeBounds::eCuboid: + ss << "Cuboid"; + break; + case VolumeBounds::eCone: + ss << "Cone"; + break; + case VolumeBounds::eCutoutCylinder: + ss << "CutoutCylinder"; + break; + case VolumeBounds::eGenericCuboid: + ss << "GenericCuboid"; + break; + case VolumeBounds::eTrapezoid: + ss << "Trapezoid"; + break; + default: + ss << "Other"; + } + + GraphViz::Node node{ + .id = name(), .label = ss.str(), .shape = GraphViz::Shape::Rectangle}; + + os << node; + + BlueprintNode::addToGraphviz(os); +} } // namespace Acts diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 70491f11e37..407c9a4713d 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -15,6 +15,8 @@ #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Logger.hpp" +#include + #include #include #include @@ -110,7 +112,8 @@ void addBlueprint(Context& ctx) { return node; } - void exit(py::object, py::object, py::object) {} + void exit(const py::object& /*type*/, const py::object& /*value*/, + const py::object& /*traceback*/) {} }; py::class_(m, "_AddStaticVolumeHelper") @@ -130,7 +133,7 @@ void addBlueprint(Context& ctx) { .def( "addStaticVolume", [](BlueprintNode& self, const Transform3& transform, - std::shared_ptr bounds, + const std::shared_ptr& bounds, const std::string& name) { auto node = std::make_shared( std::make_unique(transform, bounds, @@ -145,8 +148,8 @@ void addBlueprint(Context& ctx) { "StaticVolume", [](BlueprintNode& self, const Transform3& transform, std::shared_ptr bounds, - std::optional name = std::nullopt) { - return AddStaticVolumeHelper{self, transform, bounds, + const std::optional& name = std::nullopt) { + return AddStaticVolumeHelper{self, transform, std::move(bounds), name.value_or("undefined")}; }, py::arg("transform"), py::arg("bounds"), @@ -168,7 +171,8 @@ void addBlueprint(Context& ctx) { "CylinderContainer", [](BlueprintNode& self, BinningValue direction, std::optional name = std::nullopt) { - return AddCylinderContainerHelper{self, direction, name}; + return AddCylinderContainerHelper{self, direction, + std::move(name)}; }, py::arg("direction"), py::arg("name") = std::nullopt) @@ -181,10 +185,10 @@ void addBlueprint(Context& ctx) { .def_property_readonly("children", py::overload_cast<>(&BlueprintNode::children)) .def_property_readonly("name", &BlueprintNode::name) - .def("graphviz", - [](BlueprintNode& self, py::object fh) { + .def("graphViz", + [](BlueprintNode& self, const py::object& fh) { std::stringstream ss; - self.graphviz(ss); + self.graphViz(ss); fh.attr("write")(ss.str()); }) .def("visualize", &BlueprintNode::visualize) diff --git a/Examples/Scripts/Python/blueprint.py b/Examples/Scripts/Python/blueprint.py index b63f5fe86ec..7dadad09a15 100755 --- a/Examples/Scripts/Python/blueprint.py +++ b/Examples/Scripts/Python/blueprint.py @@ -81,7 +81,7 @@ def PixelEndcapDisk(disk): with open("blueprint.dot", "w") as fh: - root.graphviz(fh) + root.graphViz(fh) vis = acts.ObjVisualization3D() From dedc1496b55edea8d9283f7e9cfa1f8252f63299 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 28 Aug 2024 10:36:52 +0200 Subject: [PATCH 014/100] blueprint: blueprint tests, currently nullptr access --- Core/include/Acts/Geometry/BlueprintNode.hpp | 2 +- .../CylinderContainerBlueprintNode.hpp | 11 ++- .../MaterialDesignatorBlueprintNode.hpp | 4 +- .../Acts/Geometry/StaticBlueprintNode.hpp | 2 +- .../CylinderContainerBlueprintNode.cpp | 74 ++++++++++++++----- Core/src/Geometry/StaticBlueprintNode.cpp | 3 +- Examples/Scripts/Python/blueprint.py | 2 +- .../Core/Geometry/BlueprintNodeTests.cpp | 13 +++- 8 files changed, 82 insertions(+), 29 deletions(-) diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index 3ebaf98b479..4a3202a5289 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -41,7 +41,7 @@ class BlueprintNode { virtual Volume& build(const Logger& logger = Acts::getDummyLogger()) = 0; virtual PortalShellBase& connect( - const GeometryContext& gctx, + const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) = 0; // virtual void finalize(TrackingVolume& parent, diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index aff7bb4d86c..5126a9508b2 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -14,6 +14,8 @@ #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Logger.hpp" +#include + namespace Acts { class CylinderContainerBlueprintNode final : public BlueprintNode { @@ -32,7 +34,7 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { Volume& build(const Logger& logger = Acts::getDummyLogger()) override; CylinderStackPortalShell& connect( - const GeometryContext& gctx, + const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override; void visualize(IVisualization3D& vis, @@ -55,6 +57,8 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { private: void addToGraphviz(std::ostream& os) const override; + bool isGapVolume(const Volume& volume) const; + std::string m_name; BinningValue m_direction; @@ -64,8 +68,11 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { // Is only initialized during `build` std::vector m_childVolumes; std::optional m_stack{std::nullopt}; + std::map m_volumeToNode; - std::vector> m_gapVolumes; + std::vector< + std::pair, SingleCylinderPortalShell>> + m_gapVolumes; std::optional m_shell{std::nullopt}; }; diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index d73e6507d45..fa83017b650 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -32,13 +32,13 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { } PortalShellBase& connect( - const GeometryContext& gctx, + const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override { if (children().size() != 1) { throw std::runtime_error( "MaterialDesignatorBlueprintNode must have exactly one child"); } - return children().at(0).connect(gctx, logger); + return children().at(0).connect(gctx, parent, logger); } void visualize(IVisualization3D& vis, diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index d28acb6c339..c4bf3c0a698 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -24,7 +24,7 @@ class StaticBlueprintNode : public BlueprintNode { Volume& build(const Logger& logger = Acts::getDummyLogger()) override; PortalShellBase& connect( - const GeometryContext& gctx, + const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override; void visualize(IVisualization3D& vis, diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 1ce593a896e..18b0b8d4793 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -16,6 +16,8 @@ #include "Acts/Visualization/GeometryView3D.hpp" #include "Acts/Visualization/ViewConfig.hpp" +#include + namespace Acts { CylinderContainerBlueprintNode::CylinderContainerBlueprintNode( @@ -35,11 +37,16 @@ Volume& CylinderContainerBlueprintNode::build(const Logger& logger) { ACTS_DEBUG(prefix() << "cylinder container build"); if (m_stack.has_value()) { + ACTS_ERROR(prefix() << "Volume is already built"); throw std::runtime_error("Volume is already built"); } for (auto& child : children()) { - m_childVolumes.push_back(&child.build(logger)); + Volume& volume = child.build(logger); + m_childVolumes.push_back(&volume); + // We need to remember which volume we got from which child, so we can + // assemble a correct portal shell later + m_volumeToNode[&volume] = &child; } ACTS_VERBOSE(prefix() << "-> Collected " << m_childVolumes.size() << " child volumes"); @@ -55,36 +62,69 @@ Volume& CylinderContainerBlueprintNode::build(const Logger& logger) { } CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( - const GeometryContext& gctx, const Logger& logger) { + const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) { ACTS_DEBUG(prefix() << "cylinder container connect"); if (!m_stack.has_value()) { + ACTS_ERROR(prefix() << "Volume is not built"); throw std::runtime_error("Volume is not built"); } std::vector shells; - ACTS_VERBOSE("Collecting child shells from " << children().size() - << " children"); - for (auto& child : children()) { - PortalShellBase& shell = child.connect(gctx, logger); - if (auto* cylShell = dynamic_cast(&shell); - cylShell != nullptr) { - shells.push_back(cylShell); + ACTS_VERBOSE(prefix() << "Collecting child shells from " << children().size() + << " children"); + + // We have child volumes and gaps as bare Volumes in `m_childVolumes` after + // `build()` has completed. For the stack shell, we need TrackingVolumes in + // the right order. + + for (Volume* volume : m_childVolumes) { + if (isGapVolume(*volume)) { + // We need to create a TrackingVolume from the gap and put it in the shell + auto gapPtr = std::make_unique(*volume); + TrackingVolume& gap = *gapPtr; + auto& p = m_gapVolumes.emplace_back(std::move(gapPtr), + SingleCylinderPortalShell{gap}); + + shells.push_back(&p.second); } else { - throw std::runtime_error("Child volume is not a cylinder"); + // Figure out which child we got this volume from + auto it = m_volumeToNode.find(volume); + if (it == m_volumeToNode.end()) { + throw std::runtime_error("Volume not found in child volumes"); + } + BlueprintNode& child = *it->second; + + CylinderPortalShell* shell = dynamic_cast( + &child.connect(gctx, parent, logger)); + if (shell == nullptr) { + ACTS_ERROR(prefix() + << "Child volume of cylinder stack is not a cylinder"); + throw std::runtime_error( + "Child volume of cylinder stack is not a cylinder"); + } + + shells.push_back(shell); } } - ACTS_VERBOSE("Producing merged cylinder stack shell in " << m_direction - << " direction"); + // Sanity checks + throw_assert(shells.size() == m_childVolumes.size(), + "Number of shells does not match number of child volumes"); + + throw_assert(std::ranges::none_of( + shells, [](const auto* shell) { return shell == nullptr; }), + "Invalid shell pointer"); + + ACTS_VERBOSE(prefix() << "Producing merged cylinder stack shell in " + << m_direction << " direction"); m_shell.emplace(gctx, std::move(shells), m_direction, logger); return m_shell.value(); +} - // This goes into finalize at the end - // for (auto& gap : m_stack->gaps()) { - // auto tv = std::make_unique(*gap); - // parent.addVolume(std::move(tv)); - // } +bool CylinderContainerBlueprintNode::isGapVolume(const Volume& volume) const { + return std::ranges::any_of( + m_stack->gaps(), [&](const auto& gap) { return gap.get() == &volume; }); } void CylinderContainerBlueprintNode::visualize( diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index 9a69047a740..b319e927cb8 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -31,6 +31,7 @@ Volume& StaticBlueprintNode::build(const Logger& logger) { } PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, + TrackingVolume& parent, const Logger& logger) { ACTS_DEBUG(prefix() << "static connect"); if (m_volume == nullptr) { @@ -41,7 +42,7 @@ PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, << name() << ") with " << children().size() << " children"); for (auto& child : children()) { - auto& shell = child.connect(gctx, logger); + auto& shell = child.connect(gctx, parent, logger); // Register ourselves on the outside of the shell shell.connectOuter(*m_volume); } diff --git a/Examples/Scripts/Python/blueprint.py b/Examples/Scripts/Python/blueprint.py index 7dadad09a15..b4c2a0a1323 100755 --- a/Examples/Scripts/Python/blueprint.py +++ b/Examples/Scripts/Python/blueprint.py @@ -85,7 +85,7 @@ def PixelEndcapDisk(disk): vis = acts.ObjVisualization3D() -root.build(level=acts.logging.VERBOSE) +volume = root.build(level=acts.logging.VERBOSE) gctx = acts.GeometryContext() root.visualize(vis, gctx) diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index 618fb3241c2..36d1548d3a3 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -15,6 +15,7 @@ #include "Acts/Definitions/Units.hpp" #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Geometry/TrackingVolume.hpp" @@ -68,7 +69,7 @@ BOOST_AUTO_TEST_CASE(StaticBlueprintNodeConstruction) { vis.write(ofs); node.build(); - node.connect(); + // node.connect(); auto world = node.releaseVolume(); @@ -93,7 +94,7 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { } TrackingVolume dummy{Transform3::Identity(), cylBounds}; - BOOST_CHECK_THROW(root->connect(dummy), std::runtime_error); + BOOST_CHECK_THROW(root->connect(gctx, dummy), std::runtime_error); ObjVisualization3D vis; // Can't visualize before having called build @@ -105,7 +106,7 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { TrackingVolume top{world.transform(), world.volumeBoundsPtr()}; - root->connect(top, *logger); + root->connect(gctx, top, *logger); vis.write("container.obj"); } @@ -196,7 +197,11 @@ BOOST_AUTO_TEST_CASE(NodeApiTest) { vis.write("api_test.obj"); std::ofstream dot{"api_test.dot"}; - root->graphviz(dot); + root->graphViz(dot); + + auto worldTv = std::make_unique(world); + + root->connect(gctx, *worldTv, *logger); } BOOST_AUTO_TEST_SUITE_END(); From e1f490a1ac7ccb9386325d499cb9b9f7f6effbb8 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 13 Sep 2024 13:39:19 +0200 Subject: [PATCH 015/100] blueprint: some fixes after updates --- Examples/Python/src/Blueprint.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 407c9a4713d..e3c8f5cebb5 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -34,7 +34,7 @@ void addBlueprint(Context& ctx) { std::optional name; std::shared_ptr operator()( - py::function callback) { + const py::function& callback) { auto cylinder = std::make_shared( name.value_or(callback.attr("__name__").cast()), direction); @@ -53,7 +53,8 @@ void addBlueprint(Context& ctx) { return cylinder; } - void exit(py::object, py::object, py::object) {} + void exit(const py::object& /*unused*/, const py::object& /*unused*/, + const py::object& /*unused*/) {} }; py::class_(m, "_AddCylinderContainerHelper") @@ -64,7 +65,7 @@ void addBlueprint(Context& ctx) { struct AddMaterialDesignatorHelper { BlueprintNode& parent; - std::shared_ptr operator()(py::function callback) { + std::shared_ptr operator()(const py::function& callback) { auto material = std::make_shared(); parent.addChild(material); callback(material); @@ -77,7 +78,8 @@ void addBlueprint(Context& ctx) { return material; } - void exit(py::object, py::object, py::object) {} + void exit(const py::object& /*unused*/, const py::object& /*unused*/, + const py::object& /*unused*/) {} }; py::class_(m, "_AddMaterialDesignatorHelper") @@ -88,10 +90,11 @@ void addBlueprint(Context& ctx) { struct AddStaticVolumeHelper { BlueprintNode& parent; Transform3 transform; - std::shared_ptr bounds; + std::shared_ptr bounds; std::optional name; - std::shared_ptr operator()(py::function callback) { + std::shared_ptr operator()( + const py::function& callback) { std::string callbackName = callback.attr("__name__").cast(); auto node = std::make_shared( std::make_unique(transform, bounds, @@ -133,7 +136,7 @@ void addBlueprint(Context& ctx) { .def( "addStaticVolume", [](BlueprintNode& self, const Transform3& transform, - const std::shared_ptr& bounds, + const std::shared_ptr& bounds, const std::string& name) { auto node = std::make_shared( std::make_unique(transform, bounds, @@ -147,7 +150,7 @@ void addBlueprint(Context& ctx) { .def( "StaticVolume", [](BlueprintNode& self, const Transform3& transform, - std::shared_ptr bounds, + std::shared_ptr bounds, const std::optional& name = std::nullopt) { return AddStaticVolumeHelper{self, transform, std::move(bounds), name.value_or("undefined")}; @@ -225,7 +228,7 @@ void addBlueprint(Context& ctx) { std::shared_ptr>(m, "StaticBlueprintNode") .def(py::init([](const Transform3& transform, - std::shared_ptr bounds, + const std::shared_ptr& bounds, const std::string& name) { return std::make_shared( std::make_unique(transform, bounds, From f48eee3c0eb52648ef831b3f6ebba95472ddef43 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 13 Sep 2024 14:23:38 +0200 Subject: [PATCH 016/100] blueprint: Use pathlib.Path for obj output --- Examples/Scripts/Python/blueprint.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Examples/Scripts/Python/blueprint.py b/Examples/Scripts/Python/blueprint.py index b4c2a0a1323..0365edeb848 100755 --- a/Examples/Scripts/Python/blueprint.py +++ b/Examples/Scripts/Python/blueprint.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +from pathlib import Path + import acts mm = acts.UnitConstants.mm @@ -90,4 +92,4 @@ def PixelEndcapDisk(disk): gctx = acts.GeometryContext() root.visualize(vis, gctx) -vis.write("blueprint.obj") +vis.write(Path("blueprint.obj")) From cc8999a28c485a529d4b53c76415f8cc206dc018 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 13 Sep 2024 15:45:32 +0200 Subject: [PATCH 017/100] blueprint: fix vector instability --- .../Geometry/CylinderContainerBlueprintNode.hpp | 4 ++-- .../Geometry/CylinderContainerBlueprintNode.cpp | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index 5126a9508b2..57469d79c43 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -70,8 +70,8 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { std::optional m_stack{std::nullopt}; std::map m_volumeToNode; - std::vector< - std::pair, SingleCylinderPortalShell>> + std::vector, + std::unique_ptr>> m_gapVolumes; std::optional m_shell{std::nullopt}; diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 18b0b8d4793..bb8bef0e285 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -63,7 +63,7 @@ Volume& CylinderContainerBlueprintNode::build(const Logger& logger) { CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) { - ACTS_DEBUG(prefix() << "cylinder container connect"); + ACTS_DEBUG(prefix() << "Cylinder container connect"); if (!m_stack.has_value()) { ACTS_ERROR(prefix() << "Volume is not built"); throw std::runtime_error("Volume is not built"); @@ -77,16 +77,20 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( // `build()` has completed. For the stack shell, we need TrackingVolumes in // the right order. + ACTS_VERBOSE(prefix() << "Have " << m_childVolumes.size() + << " child volumes"); for (Volume* volume : m_childVolumes) { if (isGapVolume(*volume)) { // We need to create a TrackingVolume from the gap and put it in the shell auto gapPtr = std::make_unique(*volume); + ACTS_VERBOSE(prefix() << " - have gap volume: " << gapPtr); TrackingVolume& gap = *gapPtr; - auto& p = m_gapVolumes.emplace_back(std::move(gapPtr), - SingleCylinderPortalShell{gap}); + auto& p = m_gapVolumes.emplace_back( + std::move(gapPtr), std::make_unique(gap)); - shells.push_back(&p.second); + shells.push_back(p.second.get()); } else { + ACTS_VERBOSE(prefix() << "Associate child volume with child node"); // Figure out which child we got this volume from auto it = m_volumeToNode.find(volume); if (it == m_volumeToNode.end()) { @@ -94,6 +98,8 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( } BlueprintNode& child = *it->second; + ACTS_VERBOSE(prefix() << " ~> found child node " << child.name()); + CylinderPortalShell* shell = dynamic_cast( &child.connect(gctx, parent, logger)); if (shell == nullptr) { @@ -175,7 +181,7 @@ CylinderContainerBlueprintNode::setResizeStrategy( void CylinderContainerBlueprintNode::addToGraphviz(std::ostream& os) const { GraphViz::Node node{.id = name(), .label = "" + name() + "
Cylinder", - .shape = GraphViz::Shape::Folder}; + .shape = GraphViz::Shape::DoubleOctagon}; os << node << std::endl; for (const auto& child : children()) { os << indent() << GraphViz::Edge{{.id = name()}, {.id = child.name()}} From 5d3aa5dd1c49906541a38651dfc38f0d35901647 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 13 Sep 2024 15:46:20 +0200 Subject: [PATCH 018/100] blueprint: static output improvement --- Core/src/Geometry/StaticBlueprintNode.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index b319e927cb8..f5be37df389 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -33,13 +33,13 @@ Volume& StaticBlueprintNode::build(const Logger& logger) { PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) { - ACTS_DEBUG(prefix() << "static connect"); + ACTS_DEBUG(prefix() << "Static connect"); if (m_volume == nullptr) { throw std::runtime_error("Volume is not built"); } - ACTS_VERBOSE("Connecting parent volume (" - << name() << ") with " << children().size() << " children"); + ACTS_VERBOSE(prefix() << "Connecting parent volume (" << name() << ") with " + << children().size() << " children"); for (auto& child : children()) { auto& shell = child.connect(gctx, parent, logger); @@ -58,6 +58,7 @@ PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, throw std::logic_error("Volume type is not supported"); } + assert(m_shell != nullptr); return *m_shell; } From 0c834e0bdfcc1005893bdd56535a3c20599dbbcd Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 16 Sep 2024 10:49:16 +0200 Subject: [PATCH 019/100] blueprint: Uew ViewConfig designated initializers --- Core/src/Geometry/CylinderContainerBlueprintNode.cpp | 2 +- Core/src/Geometry/StaticBlueprintNode.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index bb8bef0e285..9fc67509972 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -139,7 +139,7 @@ void CylinderContainerBlueprintNode::visualize( throw std::runtime_error("Cylinder Stack Volume is not built"); } - ViewConfig viewConfig{{255, 0, 0}}; + ViewConfig viewConfig{.color = {255, 0, 0}}; for (const auto& gap : m_stack->gaps()) { GeometryView3D::drawVolume(vis, *gap, gctx, Transform3::Identity(), diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index f5be37df389..c4f69ffb4f4 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -68,7 +68,7 @@ void StaticBlueprintNode::visualize(IVisualization3D& vis, throw std::runtime_error("Volume is not built"); } - ViewConfig viewConfig{{100, 100, 100}}; + ViewConfig viewConfig{.color = {100, 100, 100}}; GeometryView3D::drawVolume(vis, *m_volume, gctx, Transform3::Identity(), viewConfig); From 97452e1e8c731dad513af5272383e569cccf052d Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 16 Sep 2024 16:09:47 +0200 Subject: [PATCH 020/100] blueprint: work on API with root builder node --- Core/include/Acts/Geometry/BlueprintNode.hpp | 3 - .../CylinderContainerBlueprintNode.hpp | 8 +- .../Acts/Geometry/RootBlueprintNode.hpp | 50 +++++++ .../Acts/Geometry/StaticBlueprintNode.hpp | 5 - Core/src/Geometry/CMakeLists.txt | 1 + .../CylinderContainerBlueprintNode.cpp | 56 ++++---- Core/src/Geometry/RootBlueprintNode.cpp | 125 ++++++++++++++++++ Core/src/Geometry/StaticBlueprintNode.cpp | 16 ++- .../Core/Geometry/BlueprintNodeTests.cpp | 48 ++++--- 9 files changed, 250 insertions(+), 62 deletions(-) create mode 100644 Core/include/Acts/Geometry/RootBlueprintNode.hpp create mode 100644 Core/src/Geometry/RootBlueprintNode.cpp diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index 4a3202a5289..48156b77412 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -44,9 +44,6 @@ class BlueprintNode { const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) = 0; - // virtual void finalize(TrackingVolume& parent, - // const Logger& logger = Acts::getDummyLogger()) = 0; - virtual void visualize(IVisualization3D& vis, const GeometryContext& gctx) const; diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index 57469d79c43..a004492a531 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -67,14 +67,12 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { // Is only initialized during `build` std::vector m_childVolumes; - std::optional m_stack{std::nullopt}; + std::unique_ptr m_stack{nullptr}; std::map m_volumeToNode; - std::vector, - std::unique_ptr>> - m_gapVolumes; + std::vector> m_gapShells; - std::optional m_shell{std::nullopt}; + std::unique_ptr m_shell{nullptr}; }; } // namespace Acts diff --git a/Core/include/Acts/Geometry/RootBlueprintNode.hpp b/Core/include/Acts/Geometry/RootBlueprintNode.hpp new file mode 100644 index 00000000000..8e27e07484f --- /dev/null +++ b/Core/include/Acts/Geometry/RootBlueprintNode.hpp @@ -0,0 +1,50 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Geometry/BlueprintNode.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/PortalShell.hpp" +#include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Geometry/TrackingVolume.hpp" + +namespace Acts { + +class RootBlueprintNode : public BlueprintNode { + public: + struct Config { + ExtentEnvelope envelope = ExtentEnvelope::Zero(); + GeometryIdentifierHook geometryIdentifierHook = {}; + }; + + RootBlueprintNode(const Config& cfg); + + const std::string& name() const override; + + void visualize(IVisualization3D& vis, + const GeometryContext& gctx) const override; + + std::unique_ptr construct( + const GeometryContext& gctx, + const Logger& logger = Acts::getDummyLogger()); + + protected: + Volume& build(const Logger& logger = Acts::getDummyLogger()) override; + + PortalShellBase& connect( + const GeometryContext& gctx, TrackingVolume& parent, + const Logger& logger = Acts::getDummyLogger()) override; + + void addToGraphviz(std::ostream& os) const override; + + private: + Config m_cfg; +}; + +} // namespace Acts diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index c4bf3c0a698..2baae5d04d8 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -30,14 +30,9 @@ class StaticBlueprintNode : public BlueprintNode { void visualize(IVisualization3D& vis, const GeometryContext& gctx) const override; - std::unique_ptr releaseVolume() { - return std::move(m_volume); - } - protected: void addToGraphviz(std::ostream& os) const override; - private: std::unique_ptr m_volume; std::unique_ptr m_shell; diff --git a/Core/src/Geometry/CMakeLists.txt b/Core/src/Geometry/CMakeLists.txt index 90f8efa876e..3b98209ff74 100644 --- a/Core/src/Geometry/CMakeLists.txt +++ b/Core/src/Geometry/CMakeLists.txt @@ -44,6 +44,7 @@ target_sources( PortalError.cpp PortalShell.cpp BlueprintNode.cpp + RootBlueprintNode.cpp CylinderContainerBlueprintNode.cpp StaticBlueprintNode.cpp Blueprint.cpp diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 9fc67509972..2ff86a1d3ab 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -9,6 +9,7 @@ #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/BlueprintNode.hpp" +#include "Acts/Geometry/CylinderVolumeStack.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/PortalShell.hpp" #include "Acts/Geometry/TrackingVolume.hpp" @@ -36,7 +37,7 @@ const std::string& CylinderContainerBlueprintNode::name() const { Volume& CylinderContainerBlueprintNode::build(const Logger& logger) { ACTS_DEBUG(prefix() << "cylinder container build"); - if (m_stack.has_value()) { + if (m_stack != nullptr) { ACTS_ERROR(prefix() << "Volume is already built"); throw std::runtime_error("Volume is already built"); } @@ -52,45 +53,47 @@ Volume& CylinderContainerBlueprintNode::build(const Logger& logger) { << " child volumes"); ACTS_VERBOSE(prefix() << "-> Building the stack"); - m_stack.emplace(m_childVolumes, m_direction, m_attachmentStrategy, - m_resizeStrategy, logger); + m_stack = std::make_unique(m_childVolumes, m_direction, + m_attachmentStrategy, + m_resizeStrategy, logger); ACTS_DEBUG(prefix() << "-> Stack bounds are: " << m_stack->volumeBounds()); ACTS_DEBUG(prefix() << " *** build complete ***"); - return m_stack.value(); + return *m_stack; } CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) { ACTS_DEBUG(prefix() << "Cylinder container connect"); - if (!m_stack.has_value()) { + if (m_stack == nullptr) { ACTS_ERROR(prefix() << "Volume is not built"); throw std::runtime_error("Volume is not built"); } std::vector shells; - ACTS_VERBOSE(prefix() << "Collecting child shells from " << children().size() - << " children"); + ACTS_DEBUG(prefix() << "Collecting child shells from " << children().size() + << " children"); // We have child volumes and gaps as bare Volumes in `m_childVolumes` after // `build()` has completed. For the stack shell, we need TrackingVolumes in // the right order. - ACTS_VERBOSE(prefix() << "Have " << m_childVolumes.size() - << " child volumes"); + ACTS_DEBUG(prefix() << "Have " << m_childVolumes.size() << " child volumes"); for (Volume* volume : m_childVolumes) { if (isGapVolume(*volume)) { // We need to create a TrackingVolume from the gap and put it in the shell - auto gapPtr = std::make_unique(*volume); - ACTS_VERBOSE(prefix() << " - have gap volume: " << gapPtr); - TrackingVolume& gap = *gapPtr; - auto& p = m_gapVolumes.emplace_back( - std::move(gapPtr), std::make_unique(gap)); + auto gap = std::make_unique(*volume); + gap->setVolumeName(name() + "::Gap" + + std::to_string(m_gapShells.size() + 1)); + ACTS_DEBUG(prefix() << " ~> Gap volume (" << gap->volumeName() + << "): " << gap->volumeBounds()); + m_gapShells.push_back(std::make_unique(*gap)); + shells.push_back(m_gapShells.back().get()); + + parent.addVolume(std::move(gap)); - shells.push_back(p.second.get()); } else { - ACTS_VERBOSE(prefix() << "Associate child volume with child node"); // Figure out which child we got this volume from auto it = m_volumeToNode.find(volume); if (it == m_volumeToNode.end()) { @@ -98,7 +101,8 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( } BlueprintNode& child = *it->second; - ACTS_VERBOSE(prefix() << " ~> found child node " << child.name()); + ACTS_DEBUG(prefix() << " ~> Child (" << child.name() + << ") volume: " << volume->volumeBounds()); CylinderPortalShell* shell = dynamic_cast( &child.connect(gctx, parent, logger)); @@ -121,21 +125,23 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( shells, [](const auto* shell) { return shell == nullptr; }), "Invalid shell pointer"); - ACTS_VERBOSE(prefix() << "Producing merged cylinder stack shell in " - << m_direction << " direction"); - m_shell.emplace(gctx, std::move(shells), m_direction, logger); + ACTS_DEBUG(prefix() << "Producing merged cylinder stack shell in " + << m_direction << " direction"); + m_shell = std::make_unique(gctx, std::move(shells), + m_direction, logger); - return m_shell.value(); + return *m_shell; } bool CylinderContainerBlueprintNode::isGapVolume(const Volume& volume) const { + assert(m_stack != nullptr); return std::ranges::any_of( m_stack->gaps(), [&](const auto& gap) { return gap.get() == &volume; }); } void CylinderContainerBlueprintNode::visualize( IVisualization3D& vis, const GeometryContext& gctx) const { - if (!m_stack.has_value()) { + if (m_stack == nullptr) { throw std::runtime_error("Cylinder Stack Volume is not built"); } @@ -151,7 +157,7 @@ void CylinderContainerBlueprintNode::visualize( CylinderContainerBlueprintNode& CylinderContainerBlueprintNode::setDirection( BinningValue direction) { - if (m_stack.has_value()) { + if (m_stack != nullptr) { throw std::runtime_error("Cannot change direction after build"); } m_direction = direction; @@ -161,7 +167,7 @@ CylinderContainerBlueprintNode& CylinderContainerBlueprintNode::setDirection( CylinderContainerBlueprintNode& CylinderContainerBlueprintNode::setAttachmentStrategy( CylinderVolumeStack::AttachmentStrategy attachmentStrategy) { - if (m_stack.has_value()) { + if (m_stack != nullptr) { throw std::runtime_error("Cannot change direction after build"); } m_attachmentStrategy = attachmentStrategy; @@ -171,7 +177,7 @@ CylinderContainerBlueprintNode::setAttachmentStrategy( CylinderContainerBlueprintNode& CylinderContainerBlueprintNode::setResizeStrategy( CylinderVolumeStack::ResizeStrategy resizeStrategy) { - if (m_stack.has_value()) { + if (m_stack != nullptr) { throw std::runtime_error("Cannot change direction after build"); } m_resizeStrategy = resizeStrategy; diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp new file mode 100644 index 00000000000..0a292e4c2e4 --- /dev/null +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -0,0 +1,125 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Geometry/RootBlueprintNode.hpp" + +#include "Acts/Geometry/CuboidVolumeBounds.hpp" +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/Extent.hpp" +#include "Acts/Geometry/PortalShell.hpp" +#include "Acts/Geometry/VolumeBounds.hpp" +#include "Acts/Utilities/GraphViz.hpp" + +namespace Acts { + +RootBlueprintNode::RootBlueprintNode(const Config &cfg) : m_cfg(cfg) {} + +const std::string &RootBlueprintNode::name() const { + static const std::string root = "root"; + return root; +} + +Volume &RootBlueprintNode::build(const Logger & /*logger*/) { + throw std::logic_error("Root node cannot be built"); +} + +PortalShellBase &RootBlueprintNode::connect(const GeometryContext & /*gctx*/, + TrackingVolume & /*parent*/, + const Logger & /*logger*/) { + throw std::logic_error("Root node cannot be connected"); +} + +void RootBlueprintNode::addToGraphviz(std::ostream &os) const { + GraphViz::Node node{ + .id = name(), .label = "Root", .shape = GraphViz::Shape::House}; + + os << node; + BlueprintNode::addToGraphviz(os); +} + +void RootBlueprintNode::visualize(IVisualization3D &vis, + const GeometryContext &gctx) const { + for (const auto &child : children()) { + child.visualize(vis, gctx); + } +} + +std::unique_ptr RootBlueprintNode::construct( + const GeometryContext &gctx, const Logger &logger) { + using enum BinningValue; + + ACTS_INFO(prefix() << "Building tracking geometry from blueprint tree"); + + if (m_cfg.envelope == ExtentEnvelope::Zero()) { + ACTS_WARNING(prefix() << "Root node is configured with zero envelope. This " + "might lead to navigation issues"); + } + + if (children().size() != 1) { + ACTS_ERROR(prefix() << "Root node must have exactly one child"); + throw std::logic_error("Root node must have exactly one child"); + } + + auto &child = children().at(0); + + ACTS_DEBUG(prefix() << "Executing building on tree"); + Volume &topVolume = child.build(logger); + const auto &bounds = topVolume.volumeBounds(); + + std::stringstream ss; + bounds.toStream(ss); + ACTS_DEBUG(prefix() << "have top volume: " << ss.str() << "\n" + << topVolume.transform().matrix()); + + std::shared_ptr worldBounds; + + if (const auto *cyl = dynamic_cast(&bounds)) { + using enum CylinderVolumeBounds::BoundValues; + + // Make a copy that we'll modify + auto newBounds = std::make_shared(*cyl); + + const auto &zEnv = m_cfg.envelope[binZ]; + if (zEnv[0] != zEnv[1]) { + ACTS_ERROR( + prefix() << "Root node cylinder envelope for z must be symmetric"); + } + + const auto &rEnv = m_cfg.envelope[binR]; + + newBounds->set({ + {eHalfLengthZ, newBounds->get(eHalfLengthZ) + zEnv[0]}, + {eMinR, std::max(0.0, newBounds->get(eMinR) - rEnv[0])}, + {eMaxR, newBounds->get(eMaxR) + rEnv[1]}, + }); + + worldBounds = std::move(newBounds); + + } else if (const auto *box = + dynamic_cast(&bounds)) { + throw std::logic_error{"Not implemented"}; + } else { + throw std::logic_error{"Unsupported volume bounds type"}; + } + + ACTS_DEBUG("New bounds are: " << *worldBounds); + + auto world = std::make_unique( + topVolume.transform(), std::move(worldBounds), "World"); + + auto &shell = child.connect(gctx, *world, logger); + + shell.connectOuter(*world); + + // @TODO: Handle material decorator, geo id hook + + return std::make_unique( + std::move(world), nullptr, m_cfg.geometryIdentifierHook, logger); +} + +} // namespace Acts diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index c4f69ffb4f4..cb3045c3027 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -26,6 +26,12 @@ Volume& StaticBlueprintNode::build(const Logger& logger) { throw std::runtime_error("Volume is not built"); } + ACTS_DEBUG(prefix() << "Building volume (" << name() << ") with " + << children().size() << " children"); + for (auto& child : children()) { + child.build(logger); + } + ACTS_DEBUG(prefix() << "-> returning volume " << *m_volume); return *m_volume; } @@ -35,11 +41,11 @@ PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, const Logger& logger) { ACTS_DEBUG(prefix() << "Static connect"); if (m_volume == nullptr) { - throw std::runtime_error("Volume is not built"); + throw std::runtime_error("Volume is not present"); } - ACTS_VERBOSE(prefix() << "Connecting parent volume (" << name() << ") with " - << children().size() << " children"); + ACTS_DEBUG(prefix() << "Connecting parent volume (" << name() << ") with " + << children().size() << " children"); for (auto& child : children()) { auto& shell = child.connect(gctx, parent, logger); @@ -58,6 +64,10 @@ PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, throw std::logic_error("Volume type is not supported"); } + ACTS_DEBUG(prefix() << " Adding volume (" << m_volume->volumeName() + << ") to parent volume (" << parent.volumeName() << ")"); + parent.addVolume(std::move(m_volume)); + assert(m_shell != nullptr); return *m_shell; } diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index 36d1548d3a3..f27569b5baf 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -17,6 +17,7 @@ #include "Acts/Geometry/CylinderVolumeBounds.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" +#include "Acts/Geometry/RootBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Geometry/TrackingVolume.hpp" #include "Acts/Utilities/Logger.hpp" @@ -27,7 +28,7 @@ using namespace Acts::UnitLiterals; namespace Acts::Test { -auto logger = Acts::getDefaultLogger("UnitTests", Acts::Logging::VERBOSE); +auto logger = Acts::getDefaultLogger("UnitTests", Acts::Logging::DEBUG); GeometryContext gctx; @@ -36,6 +37,10 @@ BOOST_AUTO_TEST_SUITE(Geometry); BOOST_AUTO_TEST_SUITE(BlueprintNodeTest); BOOST_AUTO_TEST_CASE(StaticBlueprintNodeConstruction) { + RootBlueprintNode::Config cfg; + cfg.envelope[BinningValue::binZ] = {20_mm, 2_mm}; + RootBlueprintNode root{cfg}; + ActsScalar hlZ = 30_mm; auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); auto cyl = std::make_unique(Transform3::Identity(), cylBounds, @@ -43,11 +48,11 @@ BOOST_AUTO_TEST_CASE(StaticBlueprintNodeConstruction) { const auto* cylPtr = cyl.get(); - StaticBlueprintNode node(std::move(cyl)); + auto node = std::make_unique(std::move(cyl)); - BOOST_CHECK_EQUAL(node.name(), "root"); + BOOST_CHECK_EQUAL(node->name(), "root"); - BOOST_CHECK_EQUAL(&node.build(), cylPtr); + BOOST_CHECK_EQUAL(&node->build(), cylPtr); ObjVisualization3D vis; // Add some children @@ -60,20 +65,21 @@ BOOST_AUTO_TEST_CASE(StaticBlueprintNodeConstruction) { GeometryView3D::drawVolume(vis, *childCyl, gctx); - node.addChild(std::make_unique(std::move(childCyl))); + node->addChild(std::make_unique(std::move(childCyl))); } - BOOST_CHECK_EQUAL(node.children().size(), 10); + BOOST_CHECK_EQUAL(node->children().size(), 10); + + root.addChild(std::move(node)); std::ofstream ofs{"static.obj"}; vis.write(ofs); - node.build(); - // node.connect(); + auto world = root.construct(gctx, *logger); - auto world = node.releaseVolume(); + BOOST_REQUIRE(world); - BOOST_CHECK_EQUAL(world->volumes().size(), 10); + BOOST_CHECK_EQUAL(world->highestTrackingVolume()->volumes().size(), 10); } BOOST_AUTO_TEST_CASE(CylinderContainerNode) { @@ -114,9 +120,13 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { BOOST_AUTO_TEST_CASE(NodeApiTest) { Transform3 base{AngleAxis3{30_degree, Vector3{1, 0, 0}}}; - auto root = std::make_unique( - "root", BinningValue::binZ, CylinderVolumeStack::AttachmentStrategy::Gap, - CylinderVolumeStack::ResizeStrategy::Gap); + // auto root = std::make_unique( + // "root", BinningValue::binZ, + // CylinderVolumeStack::AttachmentStrategy::Gap, + // CylinderVolumeStack::ResizeStrategy::Gap); + + RootBlueprintNode::Config cfg; + auto root = std::make_unique(cfg); root->addMaterial([&](auto& mat) { mat.addCylinderContainer("Pixel", BinningValue::binZ, [&](auto& cyl) { @@ -191,17 +201,13 @@ BOOST_AUTO_TEST_CASE(NodeApiTest) { }); }); - auto world = root->build(*logger); - ObjVisualization3D vis; - root->visualize(vis, gctx); - vis.write("api_test.obj"); - std::ofstream dot{"api_test.dot"}; root->graphViz(dot); - auto worldTv = std::make_unique(world); - - root->connect(gctx, *worldTv, *logger); + auto trackingGeometry = root->construct(gctx, *logger); + // ObjVisualization3D vis; + // root->visualize(vis, gctx); + // vis.write("api_test.obj"); } BOOST_AUTO_TEST_SUITE_END(); From 67bbdbe5f3422a894717e189ac30c490ba652200 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 16 Sep 2024 17:46:18 +0200 Subject: [PATCH 021/100] blueprint: basic trackinggeometry construction works still need to test if portals are correctly connected / registered. --- Core/include/Acts/Geometry/BlueprintNode.hpp | 14 +- .../CylinderContainerBlueprintNode.hpp | 9 +- .../MaterialDesignatorBlueprintNode.hpp | 10 +- .../Acts/Geometry/RootBlueprintNode.hpp | 8 +- .../Acts/Geometry/StaticBlueprintNode.hpp | 6 +- Core/src/Geometry/BlueprintNode.cpp | 16 +- .../CylinderContainerBlueprintNode.cpp | 59 ++-- Core/src/Geometry/RootBlueprintNode.cpp | 17 +- Core/src/Geometry/StaticBlueprintNode.cpp | 33 ++- .../Core/Geometry/BlueprintNodeTests.cpp | 254 +++++++++++------- 10 files changed, 262 insertions(+), 164 deletions(-) diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index 48156b77412..bead5704806 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -8,6 +8,7 @@ #pragma once +#include "Acts/Definitions/Algebra.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Logger.hpp" @@ -22,8 +23,8 @@ namespace Acts { class Volume; class TrackingVolume; +class VolumeBounds; class PortalShellBase; -class IVisualization3D; class CylinderContainerBlueprintNode; class MaterialDesignatorBlueprintNode; class StaticBlueprintNode; @@ -41,16 +42,21 @@ class BlueprintNode { virtual Volume& build(const Logger& logger = Acts::getDummyLogger()) = 0; virtual PortalShellBase& connect( - const GeometryContext& gctx, TrackingVolume& parent, + const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) = 0; - virtual void visualize(IVisualization3D& vis, - const GeometryContext& gctx) const; + virtual void finalize(TrackingVolume& parent, + const Logger& logger = Acts::getDummyLogger()) = 0; StaticBlueprintNode& addStaticVolume( std::unique_ptr volume, const std::function& callback = {}); + StaticBlueprintNode& addStaticVolume( + const Transform3& transform, std::shared_ptr volbounds, + const std::string& volumeName = "undefined", + const std::function& callback = {}); + CylinderContainerBlueprintNode& addCylinderContainer( const std::string& name, BinningValue direction, const std::function& diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index a004492a531..cfffd810437 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -34,11 +34,10 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { Volume& build(const Logger& logger = Acts::getDummyLogger()) override; CylinderStackPortalShell& connect( - const GeometryContext& gctx, TrackingVolume& parent, + const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void visualize(IVisualization3D& vis, - const GeometryContext& gctx) const override; + void finalize(TrackingVolume& parent, const Logger& logger) override; CylinderContainerBlueprintNode& setDirection(BinningValue direction); CylinderContainerBlueprintNode& setAttachmentStrategy( @@ -70,7 +69,9 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { std::unique_ptr m_stack{nullptr}; std::map m_volumeToNode; - std::vector> m_gapShells; + std::vector, + std::unique_ptr>> + m_gaps; std::unique_ptr m_shell{nullptr}; }; diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index fa83017b650..dc3c615cc30 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -9,6 +9,7 @@ #pragma once #include "Acts/Geometry/BlueprintNode.hpp" +#include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/GraphViz.hpp" namespace Acts { @@ -32,22 +33,21 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { } PortalShellBase& connect( - const GeometryContext& gctx, TrackingVolume& parent, + const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override { if (children().size() != 1) { throw std::runtime_error( "MaterialDesignatorBlueprintNode must have exactly one child"); } - return children().at(0).connect(gctx, parent, logger); + return children().at(0).connect(gctx, logger); } - void visualize(IVisualization3D& vis, - const GeometryContext& gctx) const override { + void finalize(TrackingVolume& parent, const Logger& logger) override { if (children().size() != 1) { throw std::runtime_error( "MaterialDesignatorBlueprintNode must have exactly one child"); } - children().at(0).visualize(vis, gctx); + return children().at(0).finalize(parent, logger); } void addToGraphviz(std::ostream& os) const override { diff --git a/Core/include/Acts/Geometry/RootBlueprintNode.hpp b/Core/include/Acts/Geometry/RootBlueprintNode.hpp index 8e27e07484f..4efc1c18db3 100644 --- a/Core/include/Acts/Geometry/RootBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/RootBlueprintNode.hpp @@ -27,9 +27,6 @@ class RootBlueprintNode : public BlueprintNode { const std::string& name() const override; - void visualize(IVisualization3D& vis, - const GeometryContext& gctx) const override; - std::unique_ptr construct( const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()); @@ -38,9 +35,12 @@ class RootBlueprintNode : public BlueprintNode { Volume& build(const Logger& logger = Acts::getDummyLogger()) override; PortalShellBase& connect( - const GeometryContext& gctx, TrackingVolume& parent, + const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; + void finalize(TrackingVolume& parent, + const Logger& logger = Acts::getDummyLogger()) override; + void addToGraphviz(std::ostream& os) const override; private: diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index 2baae5d04d8..f778bfb858f 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -24,11 +24,11 @@ class StaticBlueprintNode : public BlueprintNode { Volume& build(const Logger& logger = Acts::getDummyLogger()) override; PortalShellBase& connect( - const GeometryContext& gctx, TrackingVolume& parent, + const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void visualize(IVisualization3D& vis, - const GeometryContext& gctx) const override; + void finalize(TrackingVolume& parent, + const Logger& logger = Acts::getDummyLogger()) override; protected: void addToGraphviz(std::ostream& os) const override; diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index 21292571b0b..b939c605ebf 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -46,13 +46,6 @@ std::string BlueprintNode::prefix() const { return indent() + "[" + name() + "]: "; } -void BlueprintNode::visualize(IVisualization3D& vis, - const GeometryContext& gctx) const { - for (const auto& child : children()) { - child.visualize(vis, gctx); - } -} - StaticBlueprintNode& BlueprintNode::addStaticVolume( std::unique_ptr volume, const std::function& callback) { @@ -69,6 +62,15 @@ StaticBlueprintNode& BlueprintNode::addStaticVolume( return *child; } +StaticBlueprintNode& BlueprintNode::addStaticVolume( + const Transform3& transform, std::shared_ptr volbounds, + const std::string& volumeName, + const std::function& callback) { + return addStaticVolume(std::make_unique( + transform, std::move(volbounds), volumeName), + callback); +} + CylinderContainerBlueprintNode& BlueprintNode::addCylinderContainer( const std::string& name, BinningValue direction, const std::function& diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 2ff86a1d3ab..5ac6193b0b8 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -18,6 +18,7 @@ #include "Acts/Visualization/ViewConfig.hpp" #include +#include namespace Acts { @@ -64,7 +65,7 @@ Volume& CylinderContainerBlueprintNode::build(const Logger& logger) { } CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( - const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) { + const GeometryContext& gctx, const Logger& logger) { ACTS_DEBUG(prefix() << "Cylinder container connect"); if (m_stack == nullptr) { ACTS_ERROR(prefix() << "Volume is not built"); @@ -84,14 +85,13 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( if (isGapVolume(*volume)) { // We need to create a TrackingVolume from the gap and put it in the shell auto gap = std::make_unique(*volume); - gap->setVolumeName(name() + "::Gap" + - std::to_string(m_gapShells.size() + 1)); + gap->setVolumeName(name() + "::Gap" + std::to_string(m_gaps.size() + 1)); ACTS_DEBUG(prefix() << " ~> Gap volume (" << gap->volumeName() << "): " << gap->volumeBounds()); - m_gapShells.push_back(std::make_unique(*gap)); - shells.push_back(m_gapShells.back().get()); + auto shell = std::make_unique(*gap); + shells.push_back(shell.get()); - parent.addVolume(std::move(gap)); + m_gaps.emplace_back(std::move(shell), std::move(gap)); } else { // Figure out which child we got this volume from @@ -104,8 +104,8 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( ACTS_DEBUG(prefix() << " ~> Child (" << child.name() << ") volume: " << volume->volumeBounds()); - CylinderPortalShell* shell = dynamic_cast( - &child.connect(gctx, parent, logger)); + CylinderPortalShell* shell = + dynamic_cast(&child.connect(gctx, logger)); if (shell == nullptr) { ACTS_ERROR(prefix() << "Child volume of cylinder stack is not a cylinder"); @@ -133,26 +133,34 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( return *m_shell; } -bool CylinderContainerBlueprintNode::isGapVolume(const Volume& volume) const { - assert(m_stack != nullptr); - return std::ranges::any_of( - m_stack->gaps(), [&](const auto& gap) { return gap.get() == &volume; }); -} +void CylinderContainerBlueprintNode::finalize(TrackingVolume& parent, + const Logger& logger) { + ACTS_DEBUG(prefix() << "Finalizing cylinder container"); -void CylinderContainerBlueprintNode::visualize( - IVisualization3D& vis, const GeometryContext& gctx) const { if (m_stack == nullptr) { - throw std::runtime_error("Cylinder Stack Volume is not built"); + ACTS_ERROR(prefix() << "Volume is not built"); + throw std::runtime_error("Volume is not built"); } - ViewConfig viewConfig{.color = {255, 0, 0}}; + if (m_shell == nullptr) { + ACTS_ERROR(prefix() << "Volume is not connected"); + throw std::runtime_error("Volume is not connected"); + } - for (const auto& gap : m_stack->gaps()) { - GeometryView3D::drawVolume(vis, *gap, gctx, Transform3::Identity(), - viewConfig); + ACTS_DEBUG("Registering " << m_gaps.size() << " gap volumes with parent"); + for (auto& [shell, gap] : m_gaps) { + parent.addVolume(std::move(gap)); + shell->applyToVolume(); } + for (auto& child : children()) { + child.finalize(parent, logger); + } +} - BlueprintNode::visualize(vis, gctx); +bool CylinderContainerBlueprintNode::isGapVolume(const Volume& volume) const { + assert(m_stack != nullptr); + return std::ranges::any_of( + m_stack->gaps(), [&](const auto& gap) { return gap.get() == &volume; }); } CylinderContainerBlueprintNode& CylinderContainerBlueprintNode::setDirection( @@ -185,9 +193,12 @@ CylinderContainerBlueprintNode::setResizeStrategy( } void CylinderContainerBlueprintNode::addToGraphviz(std::ostream& os) const { - GraphViz::Node node{.id = name(), - .label = "" + name() + "
Cylinder", - .shape = GraphViz::Shape::DoubleOctagon}; + std::stringstream ss; + ss << "" + name() + ""; + ss << "
CylinderContainer"; + ss << "
dir: " << m_direction; + GraphViz::Node node{ + .id = name(), .label = ss.str(), .shape = GraphViz::Shape::DoubleOctagon}; os << node << std::endl; for (const auto& child : children()) { os << indent() << GraphViz::Edge{{.id = name()}, {.id = child.name()}} diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index 0a292e4c2e4..8c6ba80d3c9 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -29,11 +29,15 @@ Volume &RootBlueprintNode::build(const Logger & /*logger*/) { } PortalShellBase &RootBlueprintNode::connect(const GeometryContext & /*gctx*/, - TrackingVolume & /*parent*/, const Logger & /*logger*/) { throw std::logic_error("Root node cannot be connected"); } +void RootBlueprintNode::finalize(TrackingVolume & /*parent*/, + const Logger & /*logger*/) { + throw std::logic_error("Root node cannot be finalized"); +} + void RootBlueprintNode::addToGraphviz(std::ostream &os) const { GraphViz::Node node{ .id = name(), .label = "Root", .shape = GraphViz::Shape::House}; @@ -42,13 +46,6 @@ void RootBlueprintNode::addToGraphviz(std::ostream &os) const { BlueprintNode::addToGraphviz(os); } -void RootBlueprintNode::visualize(IVisualization3D &vis, - const GeometryContext &gctx) const { - for (const auto &child : children()) { - child.visualize(vis, gctx); - } -} - std::unique_ptr RootBlueprintNode::construct( const GeometryContext &gctx, const Logger &logger) { using enum BinningValue; @@ -112,10 +109,12 @@ std::unique_ptr RootBlueprintNode::construct( auto world = std::make_unique( topVolume.transform(), std::move(worldBounds), "World"); - auto &shell = child.connect(gctx, *world, logger); + auto &shell = child.connect(gctx, logger); shell.connectOuter(*world); + child.finalize(*world, logger); + // @TODO: Handle material decorator, geo id hook return std::make_unique( diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index cb3045c3027..7dcb68b6790 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -37,7 +37,6 @@ Volume& StaticBlueprintNode::build(const Logger& logger) { } PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, - TrackingVolume& parent, const Logger& logger) { ACTS_DEBUG(prefix() << "Static connect"); if (m_volume == nullptr) { @@ -48,7 +47,7 @@ PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, << children().size() << " children"); for (auto& child : children()) { - auto& shell = child.connect(gctx, parent, logger); + auto& shell = child.connect(gctx, logger); // Register ourselves on the outside of the shell shell.connectOuter(*m_volume); } @@ -64,25 +63,35 @@ PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, throw std::logic_error("Volume type is not supported"); } - ACTS_DEBUG(prefix() << " Adding volume (" << m_volume->volumeName() - << ") to parent volume (" << parent.volumeName() << ")"); - parent.addVolume(std::move(m_volume)); - assert(m_shell != nullptr); return *m_shell; } -void StaticBlueprintNode::visualize(IVisualization3D& vis, - const GeometryContext& gctx) const { +void StaticBlueprintNode::finalize(TrackingVolume& parent, + const Logger& logger) { + ACTS_DEBUG(prefix() << "Finalizing static volume"); + if (!m_volume) { + ACTS_ERROR(prefix() << "Volume is not built"); throw std::runtime_error("Volume is not built"); } - ViewConfig viewConfig{.color = {100, 100, 100}}; + if (!m_shell) { + ACTS_ERROR(prefix() << "Shell is not built"); + throw std::runtime_error("Shell is not built"); + } - GeometryView3D::drawVolume(vis, *m_volume, gctx, Transform3::Identity(), - viewConfig); - BlueprintNode::visualize(vis, gctx); + for (auto& child : children()) { + child.finalize(*m_volume, logger); + } + + ACTS_DEBUG(prefix() << "Registering " << m_shell->size() + << " portals into volume " << m_volume->volumeName()); + m_shell->applyToVolume(); + + ACTS_DEBUG(prefix() << " Adding volume (" << m_volume->volumeName() + << ") to parent volume (" << parent.volumeName() << ")"); + parent.addVolume(std::move(m_volume)); } const std::string& StaticBlueprintNode::name() const { diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index f27569b5baf..6f8f64d67de 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -86,9 +86,8 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { ActsScalar hlZ = 30_mm; auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); - auto root = std::make_unique( - "root", BinningValue::binZ, CylinderVolumeStack::AttachmentStrategy::Gap, - CylinderVolumeStack::ResizeStrategy::Gap); + RootBlueprintNode::Config cfg; + auto root = std::make_unique(cfg); ActsScalar z0 = -200_mm; for (std::size_t i = 0; i < 10; i++) { @@ -99,105 +98,99 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { root->addStaticVolume(std::move(childCyl)); } - TrackingVolume dummy{Transform3::Identity(), cylBounds}; - BOOST_CHECK_THROW(root->connect(gctx, dummy), std::runtime_error); - - ObjVisualization3D vis; - // Can't visualize before having called build - BOOST_CHECK_THROW(root->visualize(vis, gctx), std::runtime_error); + // BOOST_CHECK_THROW(root->connect(gctx), std::runtime_error); - auto world = root->build(*logger); - - root->visualize(vis, gctx); - - TrackingVolume top{world.transform(), world.volumeBoundsPtr()}; - - root->connect(gctx, top, *logger); + TrackingVolume dummy{Transform3::Identity(), cylBounds}; + // BOOST_CHECK_THROW(root->finalize(gctx, dummy), std::runtime_error); - vis.write("container.obj"); + root->construct(gctx, *logger); } -BOOST_AUTO_TEST_CASE(NodeApiTest) { +BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { Transform3 base{AngleAxis3{30_degree, Vector3{1, 0, 0}}}; - // auto root = std::make_unique( - // "root", BinningValue::binZ, - // CylinderVolumeStack::AttachmentStrategy::Gap, - // CylinderVolumeStack::ResizeStrategy::Gap); - RootBlueprintNode::Config cfg; + cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; + cfg.envelope[BinningValue::binR] = {0_mm, 20_mm}; auto root = std::make_unique(cfg); root->addMaterial([&](auto& mat) { - mat.addCylinderContainer("Pixel", BinningValue::binZ, [&](auto& cyl) { - cyl.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) - .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); - - // cyl->addStaticVolume(std::make_unique( - // base * Translation3{Vector3{0, 0, -600_mm}}, - // std::make_shared(200_mm, 400_mm, 200_mm), - // "PixelNegativeEndcap")); - - // cyl->addStaticVolume(std::make_unique( - // base * Translation3{Vector3{0, 0, 600_mm}}, - // std::make_shared(200_mm, 400_mm, 200_mm), - // "PixelPositiveEndcap")); - - // cyl->addStaticVolume(std::make_unique( - // base * Translation3{Vector3{0, 0, 0_mm}}, - // std::make_shared(100_mm, 600_mm, 200_mm), - // "PixelBarrel")); - - cyl.addCylinderContainer( - "PixelNegativeEndcap", BinningValue::binZ, [&](auto& ec) { - ec.setAttachmentStrategy( - CylinderVolumeStack::AttachmentStrategy::Gap); - - ec.addStaticVolume(std::make_unique( - base * Translation3{Vector3{0, 0, -600_mm}}, - std::make_shared(200_mm, 450_mm, 20_mm), - "PixelNeg1")); - - ec.addStaticVolume(std::make_unique( - base * Translation3{Vector3{0, 0, -400_mm}}, - std::make_shared(200_mm, 800_mm, 20_mm), - "PixelNeg2")); - }); - - cyl.addCylinderContainer( - "PixelBarrel", BinningValue::binR, [&](auto& brl) { - brl.setAttachmentStrategy( - CylinderVolumeStack::AttachmentStrategy::Gap) - .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Expand); - - brl.addStaticVolume(std::make_unique( - base, - std::make_shared(23_mm, 48_mm, 200_mm), - "PixelLayer0")); - - brl.addStaticVolume(std::make_unique( - base, - std::make_shared(87_mm, 103_mm, 250_mm), - "PixelLayer1")); - - brl.addStaticVolume(std::make_unique( - base, - std::make_shared(150_mm, 180_mm, 310_mm), - "PixelLayer2")); - - brl.addStaticVolume(std::make_unique( - base, - std::make_shared(250_mm, 400_mm, 310_mm), - "PixelLayer3")); - }); - - auto& ec = - cyl.addCylinderContainer("PixelPosWrapper", BinningValue::binR); - ec.setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); - ec.addStaticVolume(std::make_unique( - base * Translation3{Vector3{0, 0, 600_mm}}, - std::make_shared(150_mm, 390_mm, 200_mm), - "PixelPositiveEndcap")); + mat.addCylinderContainer("Detector", BinningValue::binR, [&](auto& det) { + det.addCylinderContainer("Pixel", BinningValue::binZ, [&](auto& cyl) { + cyl.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) + .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); + + // cyl->addStaticVolume(std::make_unique( + // base * Translation3{Vector3{0, 0, -600_mm}}, + // std::make_shared(200_mm, 400_mm, 200_mm), + // "PixelNegativeEndcap")); + + // cyl->addStaticVolume(std::make_unique( + // base * Translation3{Vector3{0, 0, 600_mm}}, + // std::make_shared(200_mm, 400_mm, 200_mm), + // "PixelPositiveEndcap")); + + // cyl->addStaticVolume(std::make_unique( + // base * Translation3{Vector3{0, 0, 0_mm}}, + // std::make_shared(100_mm, 600_mm, 200_mm), + // "PixelBarrel")); + + cyl.addCylinderContainer( + "PixelNegativeEndcap", BinningValue::binZ, [&](auto& ec) { + ec.setAttachmentStrategy( + CylinderVolumeStack::AttachmentStrategy::Gap); + + ec.addStaticVolume( + base * Translation3{Vector3{0, 0, -600_mm}}, + std::make_shared(200_mm, 450_mm, 20_mm), + "PixelNeg1"); + + ec.addStaticVolume( + base * Translation3{Vector3{0, 0, -400_mm}}, + std::make_shared(200_mm, 800_mm, 20_mm), + "PixelNeg2"); + }); + + cyl.addCylinderContainer( + "PixelBarrel", BinningValue::binR, [&](auto& brl) { + brl.setAttachmentStrategy( + CylinderVolumeStack::AttachmentStrategy::Gap) + .setResizeStrategy( + CylinderVolumeStack::ResizeStrategy::Expand); + + brl.addStaticVolume( + base, + std::make_shared(23_mm, 48_mm, 200_mm), + "PixelLayer0"); + + brl.addStaticVolume( + base, + std::make_shared(87_mm, 103_mm, 250_mm), + "PixelLayer1"); + + brl.addStaticVolume(base, + std::make_shared( + 150_mm, 180_mm, 310_mm), + "PixelLayer2"); + + brl.addStaticVolume(base, + std::make_shared( + 250_mm, 400_mm, 310_mm), + "PixelLayer3"); + }); + + auto& ec = + cyl.addCylinderContainer("PixelPosWrapper", BinningValue::binR); + ec.setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); + ec.addStaticVolume(std::make_unique( + base * Translation3{Vector3{0, 0, 600_mm}}, + std::make_shared(150_mm, 390_mm, 200_mm), + "PixelPositiveEndcap")); + }); + + det.addStaticVolume( + base, std::make_shared(0_mm, 23_mm, 1000_mm), + "BeamPipe"); }); }); @@ -205,11 +198,88 @@ BOOST_AUTO_TEST_CASE(NodeApiTest) { root->graphViz(dot); auto trackingGeometry = root->construct(gctx, *logger); + + trackingGeometry->visitVolumes([](const TrackingVolume* volume) { + std::cout << volume->volumeName() << std::endl; + std::cout << " -> id: " << volume->geometryId() << std::endl; + std::cout << " -> " << volume->portals().size() << " portals" << std::endl; + }); + // ObjVisualization3D vis; // root->visualize(vis, gctx); // vis.write("api_test.obj"); } +BOOST_AUTO_TEST_CASE(NodeApiTestConfined) { + Transform3 base{AngleAxis3{30_degree, Vector3{1, 0, 0}}}; + + RootBlueprintNode::Config cfg; + cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; + cfg.envelope[BinningValue::binR] = {0_mm, 20_mm}; + auto root = std::make_unique(cfg); + + root->addCylinderContainer("Detector", BinningValue::binR, [&](auto& det) { + det.addStaticVolume( + base, std::make_shared(50_mm, 400_mm, 1000_mm), + "PixelWrapper", [&](auto& wrap) { + ActsScalar rMin = 100_mm; + ActsScalar rMax = 350_mm; + ActsScalar hlZ = 100_mm; + + wrap.addStaticVolume( + base * Translation3{Vector3{0, 0, -600_mm}}, + std::make_shared(rMin, rMax, hlZ), + "PixelNeg1"); + + wrap.addStaticVolume( + base * Translation3{Vector3{0, 0, -200_mm}}, + std::make_shared(rMin, rMax, hlZ), + "PixelNeg2"); + + wrap.addStaticVolume( + base * Translation3{Vector3{0, 0, 200_mm}}, + std::make_shared(rMin, rMax, hlZ), + "PixelPos1"); + + wrap.addStaticVolume( + base * Translation3{Vector3{0, 0, 600_mm}}, + std::make_shared(rMin, rMax, hlZ), + "PixelPos2"); + }); + + det.addStaticVolume( + base, std::make_shared(0_mm, 23_mm, 1000_mm), + "BeamPipe"); + }); + + std::ofstream dot{"api_test_confined.dot"}; + root->graphViz(dot); + + auto trackingGeometry = root->construct(gctx, *logger); + + ObjVisualization3D vis; + + trackingGeometry->visitVolumes([&](const TrackingVolume* volume) { + std::cout << volume->volumeName() << std::endl; + std::cout << " -> id: " << volume->geometryId() << std::endl; + std::cout << " -> " << volume->portals().size() << " portals" << std::endl; + + GeometryView3D::drawVolume(vis, *volume, gctx, Transform3::Identity(), + {.color = {123, 123, 123}}); + }); + + vis.write("api_test_confined.obj"); + + const auto* wrapper = + trackingGeometry->findVolume(GeometryIdentifier{}.setVolume(2)); + BOOST_REQUIRE_NE(wrapper, nullptr); + + std::cout << wrapper->volumeName() << std::endl; + + BOOST_CHECK_EQUAL(wrapper->portals().size(), 20); + BOOST_CHECK_EQUAL(wrapper->volumes().size(), 4); +} + BOOST_AUTO_TEST_SUITE_END(); BOOST_AUTO_TEST_SUITE_END(); From 75d21c3cc3b058bbfce05d4d57f1ff9f55b4e5c1 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 20 Sep 2024 12:04:18 +0200 Subject: [PATCH 022/100] blueprint: Python bindings visualize removal --- Examples/Python/src/Blueprint.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index e3c8f5cebb5..8970a56bad3 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -194,7 +194,6 @@ void addBlueprint(Context& ctx) { self.graphViz(ss); fh.attr("write")(ss.str()); }) - .def("visualize", &BlueprintNode::visualize) .def( "build", [](BlueprintNode& self, Logging::Level level) { From a99776d52ff14ca246814e8f5666ff582e4c74b6 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 20 Sep 2024 12:06:30 +0200 Subject: [PATCH 023/100] blueprint: Output and assertions --- .../CylinderContainerBlueprintNode.cpp | 18 ++++++++++++++++-- Core/src/Geometry/RootBlueprintNode.cpp | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 5ac6193b0b8..4747b702cda 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -89,6 +89,7 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( ACTS_DEBUG(prefix() << " ~> Gap volume (" << gap->volumeName() << "): " << gap->volumeBounds()); auto shell = std::make_unique(*gap); + assert(shell->isValid()); shells.push_back(shell.get()); m_gaps.emplace_back(std::move(shell), std::move(gap)); @@ -112,6 +113,7 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( throw std::runtime_error( "Child volume of cylinder stack is not a cylinder"); } + assert(shell->isValid()); shells.push_back(shell); } @@ -125,11 +127,18 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( shells, [](const auto* shell) { return shell == nullptr; }), "Invalid shell pointer"); + throw_assert(std::ranges::all_of( + shells, [](const auto* shell) { return shell->isValid(); }), + "Invalid shell"); + ACTS_DEBUG(prefix() << "Producing merged cylinder stack shell in " - << m_direction << " direction"); + << m_direction << " direction from " << shells.size() + << " shells"); m_shell = std::make_unique(gctx, std::move(shells), m_direction, logger); + assert(m_shell != nullptr && "No shell was built at the end of connect"); + assert(m_shell->isValid() && "Shell is not valid at the end of connect"); return *m_shell; } @@ -147,11 +156,16 @@ void CylinderContainerBlueprintNode::finalize(TrackingVolume& parent, throw std::runtime_error("Volume is not connected"); } - ACTS_DEBUG("Registering " << m_gaps.size() << " gap volumes with parent"); + ACTS_DEBUG(prefix() << "Registering " << m_gaps.size() + << " gap volumes with parent"); for (auto& [shell, gap] : m_gaps) { + std::cout << "~> " << gap->volumeName() << std::endl; parent.addVolume(std::move(gap)); shell->applyToVolume(); } + + ACTS_DEBUG(prefix() << "Finalizing " << children().size() << " children"); + for (auto& child : children()) { child.finalize(parent, logger); } diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index 8c6ba80d3c9..249234e96da 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -104,7 +104,7 @@ std::unique_ptr RootBlueprintNode::construct( throw std::logic_error{"Unsupported volume bounds type"}; } - ACTS_DEBUG("New bounds are: " << *worldBounds); + ACTS_DEBUG(prefix() << "New root volume bounds are: " << *worldBounds); auto world = std::make_unique( topVolume.transform(), std::move(worldBounds), "World"); From a4b6000ce77fe7dd5e247447822a95390433e098 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 23 Sep 2024 15:57:44 +0200 Subject: [PATCH 024/100] blueprint: Basic pseudo stepping test works --- .../CylinderContainerBlueprintNode.cpp | 3 + Core/src/Geometry/RootBlueprintNode.cpp | 8 + Core/src/Geometry/StaticBlueprintNode.cpp | 10 +- .../Core/Geometry/BlueprintNodeTests.cpp | 245 +++++++++++++++--- 4 files changed, 230 insertions(+), 36 deletions(-) diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 4747b702cda..47484fe8d49 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -160,6 +160,9 @@ void CylinderContainerBlueprintNode::finalize(TrackingVolume& parent, << " gap volumes with parent"); for (auto& [shell, gap] : m_gaps) { std::cout << "~> " << gap->volumeName() << std::endl; + // @TODO: This needs to become configurable + gap->setNavigationDelegate( + std::make_unique(*gap)); parent.addVolume(std::move(gap)); shell->applyToVolume(); } diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index 249234e96da..c8f37eef508 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -109,6 +109,14 @@ std::unique_ptr RootBlueprintNode::construct( auto world = std::make_unique( topVolume.transform(), std::move(worldBounds), "World"); + // @TODO: This needs to become configurable + world->setNavigationDelegate( + std::make_unique(*world)); + + // Need one-sided portal shell that connects outwards to nullptr + SingleCylinderPortalShell worldShell{*world}; + worldShell.applyToVolume(); + auto &shell = child.connect(gctx, logger); shell.connectOuter(*world); diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index 7dcb68b6790..30aa3ecb86d 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -63,7 +63,10 @@ PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, throw std::logic_error("Volume type is not supported"); } - assert(m_shell != nullptr); + assert(m_shell != nullptr && + "No shell was built at the end of StaticBlueprintNode::connect"); + assert(m_shell->isValid() && + "Shell is not valid at the end of StaticBlueprintNode::connect"); return *m_shell; } @@ -91,6 +94,11 @@ void StaticBlueprintNode::finalize(TrackingVolume& parent, ACTS_DEBUG(prefix() << " Adding volume (" << m_volume->volumeName() << ") to parent volume (" << parent.volumeName() << ")"); + + // @TODO: This needs to become configurable + m_volume->setNavigationDelegate( + std::make_unique(*m_volume)); + parent.addVolume(std::move(m_volume)); } diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index 6f8f64d67de..a565ea76987 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -20,10 +20,13 @@ #include "Acts/Geometry/RootBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Navigation/NavigationDelegate.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Visualization/GeometryView3D.hpp" #include "Acts/Visualization/ObjVisualization3D.hpp" +#include + using namespace Acts::UnitLiterals; namespace Acts::Test { @@ -75,11 +78,16 @@ BOOST_AUTO_TEST_CASE(StaticBlueprintNodeConstruction) { std::ofstream ofs{"static.obj"}; vis.write(ofs); - auto world = root.construct(gctx, *logger); + auto tGeometry = root.construct(gctx, *logger); + + BOOST_REQUIRE(tGeometry); - BOOST_REQUIRE(world); + BOOST_CHECK_EQUAL(tGeometry->highestTrackingVolume()->volumes().size(), 1); + std::size_t nVolumes = 0; + tGeometry->visitVolumes( + [&](const TrackingVolume* /*volume*/) { nVolumes++; }); - BOOST_CHECK_EQUAL(world->highestTrackingVolume()->volumes().size(), 10); + BOOST_CHECK_EQUAL(nVolumes, 12); } BOOST_AUTO_TEST_CASE(CylinderContainerNode) { @@ -87,27 +95,169 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); RootBlueprintNode::Config cfg; + cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; + cfg.envelope[BinningValue::binR] = {0_mm, 20_mm}; auto root = std::make_unique(cfg); + auto& cyl = root->addCylinderContainer("Container", BinningValue::binZ); + ActsScalar z0 = -200_mm; for (std::size_t i = 0; i < 10; i++) { auto childCyl = std::make_unique( Transform3::Identity() * Translation3{Vector3{0, 0, z0 + i * 2 * hlZ * 1.2}}, cylBounds, "child" + std::to_string(i)); - root->addStaticVolume(std::move(childCyl)); + cyl.addStaticVolume(std::move(childCyl)); } - // BOOST_CHECK_THROW(root->connect(gctx), std::runtime_error); + root->construct(gctx, *logger); +} - TrackingVolume dummy{Transform3::Identity(), cylBounds}; - // BOOST_CHECK_THROW(root->finalize(gctx, dummy), std::runtime_error); +void pseudoNavigation(const TrackingGeometry& trackingGeometry, + Vector3 position, const Vector3& direction, + std::ostream& csv, std::size_t run, + std::size_t substepsPerCm = 1) { + std::mt19937 rng{static_cast(run)}; + std::uniform_real_distribution<> dist{0.01, 0.99}; - root->construct(gctx, *logger); + const auto* volume = trackingGeometry.lowestTrackingVolume(gctx, position); + BOOST_REQUIRE_NE(volume, nullptr); + std::cout << volume->volumeName() << std::endl; + + Experimental::Gen3Geometry::NavigationState state; + state.currentVolume = volume; + + csv << run << "," << position[0] << "," << position[1] << "," << position[2]; + csv << "," << volume->geometryId().volume(); + csv << "," << volume->geometryId().boundary(); + csv << std::endl; + + std::cout << "start pseudo navigation" << std::endl; + + for (std::size_t i = 0; i < 100; i++) { + state.main = NavigationStream{}; + + state.currentVolume->updateNavigationState(state); + + std::cout << state.main.candidates().size() << " candidates" << std::endl; + + for (const auto& candidate : state.main.candidates()) { + std::cout << " -> " << candidate.surface().geometryId() << std::endl; + std::cout << " " << candidate.surface().toStream(gctx) << std::endl; + } + + std::cout << "initializing candidates" << std::endl; + state.main.initialize(gctx, {position, direction}, + BoundaryTolerance::None()); + + std::cout << state.main.candidates().size() << " candidates remaining" + << std::endl; + + for (const auto& candidate : state.main.candidates()) { + std::cout << " -> " << candidate.surface().geometryId() << std::endl; + std::cout << " " << candidate.surface().toStream(gctx) << std::endl; + } + + if (state.main.currentCandidate().surface().isOnSurface(gctx, position, + direction)) { + std::cout << "Already on portal at initialization, skipping candidate" + << std::endl; + + auto id = state.main.currentCandidate().surface().geometryId(); + csv << run << "," << position[0] << "," << position[1] << "," + << position[2]; + csv << "," << id.volume(); + csv << "," << id.boundary(); + csv << std::endl; + if (!state.main.switchToNextCandidate()) { + std::cout << "candidates exhausted unexpectedly" << std::endl; + break; + } + } + + const auto& candidate = state.main.currentCandidate(); + std::cout << candidate.portal << std::endl; + std::cout << candidate.intersection.position().transpose() << std::endl; + + BOOST_REQUIRE_NE(candidate.portal, nullptr); + + std::cout << "on portal: " << candidate.portal->surface().geometryId() + << std::endl; + + std::cout << "moving to position: " << position.transpose() + << " (r=" << VectorHelpers::perp(position) << ")\n"; + Vector3 delta = candidate.intersection.position() - position; + + std::size_t substeps = + std::max(1l, std::lround(delta.norm() / 10_cm * substepsPerCm)); + + for (std::size_t j = 0; j < substeps; j++) { + // position += delta / (substeps + 1); + Vector3 subpos = position + dist(rng) * delta; + csv << run << "," << subpos[0] << "," << subpos[1] << "," << subpos[2]; + csv << "," << state.currentVolume->geometryId().volume(); + csv << "," << state.currentVolume->geometryId().boundary(); + csv << std::endl; + } + + position = candidate.intersection.position(); + + std::cout << " -> " << position.transpose() + << " (r=" << VectorHelpers::perp(position) << ")" << std::endl; + + state.currentVolume = + candidate.portal->resolveVolume(gctx, position, direction).value(); + + if (state.currentVolume == nullptr) { + std::cout << "switched to nullptr" << std::endl; + break; + } + + std::cout << "switched to " << state.currentVolume->volumeName() + << std::endl; + + std::cout << "-----" << std::endl; + } +} + +void portalSamples(const TrackingGeometry& trackingGeometry, Vector3 position, + const Vector3& direction, std::ostream& csv, + std::size_t run) { + std::set visitedSurfaces; + + trackingGeometry.visitVolumes([&](const TrackingVolume* volume) { + for (const auto& portal : volume->portals()) { + if (visitedSurfaces.contains(&portal.surface())) { + continue; + } + visitedSurfaces.insert(&portal.surface()); + + auto multiIntersection = portal.surface().intersect( + gctx, position, direction, BoundaryTolerance::None()); + + for (const auto& intersection : multiIntersection.split()) { + if (intersection.isValid()) { + Vector3 newPosition = intersection.position(); + csv << run << "," << position[0] << "," << position[1] << "," + << position[2]; + csv << "," << volume->geometryId().volume(); + csv << "," << volume->geometryId().boundary(); + csv << std::endl; + csv << run << "," << newPosition[0] << "," << newPosition[1] << "," + << newPosition[2]; + csv << "," << portal.surface().geometryId().volume(); + csv << "," << portal.surface().geometryId().boundary(); + csv << std::endl; + position = newPosition; + } + } + } + }); } BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { - Transform3 base{AngleAxis3{30_degree, Vector3{1, 0, 0}}}; + // Transform3 base{AngleAxis3{30_degree, Vector3{1, 0, 0}}}; + Transform3 base{Transform3::Identity()}; RootBlueprintNode::Config cfg; cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; @@ -120,21 +270,6 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { cyl.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); - // cyl->addStaticVolume(std::make_unique( - // base * Translation3{Vector3{0, 0, -600_mm}}, - // std::make_shared(200_mm, 400_mm, 200_mm), - // "PixelNegativeEndcap")); - - // cyl->addStaticVolume(std::make_unique( - // base * Translation3{Vector3{0, 0, 600_mm}}, - // std::make_shared(200_mm, 400_mm, 200_mm), - // "PixelPositiveEndcap")); - - // cyl->addStaticVolume(std::make_unique( - // base * Translation3{Vector3{0, 0, 0_mm}}, - // std::make_shared(100_mm, 600_mm, 200_mm), - // "PixelBarrel")); - cyl.addCylinderContainer( "PixelNegativeEndcap", BinningValue::binZ, [&](auto& ec) { ec.setAttachmentStrategy( @@ -194,24 +329,65 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { }); }); - std::ofstream dot{"api_test.dot"}; + std::ofstream dot{"api_test_container.dot"}; root->graphViz(dot); auto trackingGeometry = root->construct(gctx, *logger); - trackingGeometry->visitVolumes([](const TrackingVolume* volume) { + trackingGeometry->visitVolumes([&](const TrackingVolume* volume) { std::cout << volume->volumeName() << std::endl; std::cout << " -> id: " << volume->geometryId() << std::endl; std::cout << " -> " << volume->portals().size() << " portals" << std::endl; }); - // ObjVisualization3D vis; - // root->visualize(vis, gctx); - // vis.write("api_test.obj"); + ObjVisualization3D vis; + + trackingGeometry->visualize(vis, gctx, {}, {}); + + vis.write("api_test_container.obj"); + + Vector3 position = Vector3::Zero(); + std::ofstream csv{"api_test_container.csv"}; + csv << "x,y,z,volume,boundary" << std::endl; + + std::mt19937 rnd{42}; + + std::uniform_real_distribution<> dist{-1, 1}; + + double etaWidth = 5.0; + double thetaMin = 2 * std::atan(std::exp(-etaWidth)); + double thetaMax = 2 * std::atan(std::exp(etaWidth)); + std::uniform_real_distribution<> thetaDist{thetaMin, thetaMax}; + + using namespace Acts::UnitLiterals; + + for (std::size_t i = 0; i < 5000; i++) { + // double eta = 1.0; + // double theta = 2 * std::atan(std::exp(-eta)); + + double theta = thetaDist(rnd); + double phi = 2 * M_PI * dist(rnd); + + Vector3 direction; + direction[0] = std::sin(theta) * std::cos(phi); + direction[1] = std::sin(theta) * std::sin(phi); + direction[2] = std::cos(theta); + + std::cout << "start navigation " << i << std::endl; + std::cout << "dir: " << direction.transpose() << std::endl; + std::cout << direction.norm() << std::endl; + + pseudoNavigation(*trackingGeometry, position, direction, csv, i, 2); + + // portalSamples(*trackingGeometry, position, direction, csv, i); + + // break; + } } BOOST_AUTO_TEST_CASE(NodeApiTestConfined) { - Transform3 base{AngleAxis3{30_degree, Vector3{1, 0, 0}}}; + // Transform3 base{AngleAxis3{30_degree, Vector3{1, 0, 0}}}; + Transform3 base{Transform3::Identity()}; RootBlueprintNode::Config cfg; cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; @@ -257,17 +433,16 @@ BOOST_AUTO_TEST_CASE(NodeApiTestConfined) { auto trackingGeometry = root->construct(gctx, *logger); - ObjVisualization3D vis; - trackingGeometry->visitVolumes([&](const TrackingVolume* volume) { std::cout << volume->volumeName() << std::endl; std::cout << " -> id: " << volume->geometryId() << std::endl; std::cout << " -> " << volume->portals().size() << " portals" << std::endl; - - GeometryView3D::drawVolume(vis, *volume, gctx, Transform3::Identity(), - {.color = {123, 123, 123}}); }); + ObjVisualization3D vis; + + trackingGeometry->visualize(vis, gctx, {}, {}); + vis.write("api_test_confined.obj"); const auto* wrapper = From 7463da263a9e350a5c3e5764e20a48663cd75b5b Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 23 Sep 2024 17:10:52 +0200 Subject: [PATCH 025/100] blueprint: NavigationDelegate -> NavigationPolicy --- Core/src/Geometry/CylinderContainerBlueprintNode.cpp | 4 ++-- Core/src/Geometry/RootBlueprintNode.cpp | 4 ++-- Core/src/Geometry/StaticBlueprintNode.cpp | 4 ++-- Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp | 1 - 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 47484fe8d49..438789d93cb 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -161,8 +161,8 @@ void CylinderContainerBlueprintNode::finalize(TrackingVolume& parent, for (auto& [shell, gap] : m_gaps) { std::cout << "~> " << gap->volumeName() << std::endl; // @TODO: This needs to become configurable - gap->setNavigationDelegate( - std::make_unique(*gap)); + gap->setNavigationPolicy( + std::make_unique(*gap)); parent.addVolume(std::move(gap)); shell->applyToVolume(); } diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index c8f37eef508..845368be28b 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -110,8 +110,8 @@ std::unique_ptr RootBlueprintNode::construct( topVolume.transform(), std::move(worldBounds), "World"); // @TODO: This needs to become configurable - world->setNavigationDelegate( - std::make_unique(*world)); + world->setNavigationPolicy( + std::make_unique(*world)); // Need one-sided portal shell that connects outwards to nullptr SingleCylinderPortalShell worldShell{*world}; diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index 30aa3ecb86d..20e04e18a14 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -96,8 +96,8 @@ void StaticBlueprintNode::finalize(TrackingVolume& parent, << ") to parent volume (" << parent.volumeName() << ")"); // @TODO: This needs to become configurable - m_volume->setNavigationDelegate( - std::make_unique(*m_volume)); + m_volume->setNavigationPolicy( + std::make_unique(*m_volume)); parent.addVolume(std::move(m_volume)); } diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index a565ea76987..2ba038f0ef0 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -20,7 +20,6 @@ #include "Acts/Geometry/RootBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Geometry/TrackingVolume.hpp" -#include "Acts/Navigation/NavigationDelegate.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Visualization/GeometryView3D.hpp" #include "Acts/Visualization/ObjVisualization3D.hpp" From 6ada37d5788c5a1be784b8af5dd2780931ce7bde Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Thu, 26 Sep 2024 13:17:53 +0200 Subject: [PATCH 026/100] blueprint: Update after delegate / policy change --- .../CylinderContainerBlueprintNode.cpp | 2 +- Core/src/Geometry/RootBlueprintNode.cpp | 1 + Core/src/Geometry/StaticBlueprintNode.cpp | 2 +- .../Core/Geometry/BlueprintNodeTests.cpp | 42 +++++++++---------- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 438789d93cb..5d250d96b4b 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -13,9 +13,9 @@ #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/PortalShell.hpp" #include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Navigation/NavigationPolicy.hpp" #include "Acts/Utilities/GraphViz.hpp" #include "Acts/Visualization/GeometryView3D.hpp" -#include "Acts/Visualization/ViewConfig.hpp" #include #include diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index 845368be28b..50cdbe081c2 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -13,6 +13,7 @@ #include "Acts/Geometry/Extent.hpp" #include "Acts/Geometry/PortalShell.hpp" #include "Acts/Geometry/VolumeBounds.hpp" +#include "Acts/Navigation/NavigationPolicy.hpp" #include "Acts/Utilities/GraphViz.hpp" namespace Acts { diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index 20e04e18a14..1699aec0609 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -11,9 +11,9 @@ #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/PortalShell.hpp" #include "Acts/Geometry/VolumeBounds.hpp" +#include "Acts/Navigation/NavigationPolicy.hpp" #include "Acts/Utilities/GraphViz.hpp" #include "Acts/Visualization/GeometryView3D.hpp" -#include "Acts/Visualization/ViewConfig.hpp" namespace Acts { diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index 2ba038f0ef0..a314b2b140f 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -20,6 +20,7 @@ #include "Acts/Geometry/RootBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Navigation/NavigationStream.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Visualization/GeometryView3D.hpp" #include "Acts/Visualization/ObjVisualization3D.hpp" @@ -123,8 +124,8 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, BOOST_REQUIRE_NE(volume, nullptr); std::cout << volume->volumeName() << std::endl; - Experimental::Gen3Geometry::NavigationState state; - state.currentVolume = volume; + NavigationStream main; + const TrackingVolume* currentVolume = volume; csv << run << "," << position[0] << "," << position[1] << "," << position[2]; csv << "," << volume->geometryId().volume(); @@ -134,47 +135,47 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, std::cout << "start pseudo navigation" << std::endl; for (std::size_t i = 0; i < 100; i++) { - state.main = NavigationStream{}; + main = NavigationStream{}; - state.currentVolume->updateNavigationState(state); + currentVolume->updateNavigationState( + {.main = main, .position = position, .direction = direction}); - std::cout << state.main.candidates().size() << " candidates" << std::endl; + std::cout << main.candidates().size() << " candidates" << std::endl; - for (const auto& candidate : state.main.candidates()) { + for (const auto& candidate : main.candidates()) { std::cout << " -> " << candidate.surface().geometryId() << std::endl; std::cout << " " << candidate.surface().toStream(gctx) << std::endl; } std::cout << "initializing candidates" << std::endl; - state.main.initialize(gctx, {position, direction}, - BoundaryTolerance::None()); + main.initialize(gctx, {position, direction}, BoundaryTolerance::None()); - std::cout << state.main.candidates().size() << " candidates remaining" + std::cout << main.candidates().size() << " candidates remaining" << std::endl; - for (const auto& candidate : state.main.candidates()) { + for (const auto& candidate : main.candidates()) { std::cout << " -> " << candidate.surface().geometryId() << std::endl; std::cout << " " << candidate.surface().toStream(gctx) << std::endl; } - if (state.main.currentCandidate().surface().isOnSurface(gctx, position, - direction)) { + if (main.currentCandidate().surface().isOnSurface(gctx, position, + direction)) { std::cout << "Already on portal at initialization, skipping candidate" << std::endl; - auto id = state.main.currentCandidate().surface().geometryId(); + auto id = main.currentCandidate().surface().geometryId(); csv << run << "," << position[0] << "," << position[1] << "," << position[2]; csv << "," << id.volume(); csv << "," << id.boundary(); csv << std::endl; - if (!state.main.switchToNextCandidate()) { + if (!main.switchToNextCandidate()) { std::cout << "candidates exhausted unexpectedly" << std::endl; break; } } - const auto& candidate = state.main.currentCandidate(); + const auto& candidate = main.currentCandidate(); std::cout << candidate.portal << std::endl; std::cout << candidate.intersection.position().transpose() << std::endl; @@ -194,8 +195,8 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, // position += delta / (substeps + 1); Vector3 subpos = position + dist(rng) * delta; csv << run << "," << subpos[0] << "," << subpos[1] << "," << subpos[2]; - csv << "," << state.currentVolume->geometryId().volume(); - csv << "," << state.currentVolume->geometryId().boundary(); + csv << "," << currentVolume->geometryId().volume(); + csv << "," << currentVolume->geometryId().boundary(); csv << std::endl; } @@ -204,16 +205,15 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, std::cout << " -> " << position.transpose() << " (r=" << VectorHelpers::perp(position) << ")" << std::endl; - state.currentVolume = + currentVolume = candidate.portal->resolveVolume(gctx, position, direction).value(); - if (state.currentVolume == nullptr) { + if (currentVolume == nullptr) { std::cout << "switched to nullptr" << std::endl; break; } - std::cout << "switched to " << state.currentVolume->volumeName() - << std::endl; + std::cout << "switched to " << currentVolume->volumeName() << std::endl; std::cout << "-----" << std::endl; } From 43042a00095a140a3ac8bc28d5f17b7663df6582 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 30 Sep 2024 14:50:06 +0200 Subject: [PATCH 027/100] blueprint: add options struct being passed through building functions --- Core/include/Acts/Geometry/BlueprintNode.hpp | 12 +++++++++--- .../CylinderContainerBlueprintNode.hpp | 8 +++++--- .../MaterialDesignatorBlueprintNode.hpp | 15 +++++++++------ .../Acts/Geometry/RootBlueprintNode.hpp | 9 +++++---- .../Acts/Geometry/StaticBlueprintNode.hpp | 7 ++++--- Core/src/Geometry/BlueprintNode.cpp | 2 ++ .../CylinderContainerBlueprintNode.cpp | 18 ++++++++++-------- Core/src/Geometry/RootBlueprintNode.cpp | 19 ++++++++++++------- Core/src/Geometry/StaticBlueprintNode.cpp | 15 +++++++++------ Examples/Python/src/Blueprint.cpp | 3 ++- .../Core/Geometry/BlueprintNodeTests.cpp | 11 ++++++----- 11 files changed, 73 insertions(+), 46 deletions(-) diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index bead5704806..e49ff428977 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -10,6 +10,7 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/NavigationPolicyFactory.hpp" #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Utilities/TransformRange.hpp" @@ -31,6 +32,10 @@ class StaticBlueprintNode; class BlueprintNode { public: + struct Options { + void validate() const; + }; + BlueprintNode() = default; virtual ~BlueprintNode() = default; @@ -39,13 +44,14 @@ class BlueprintNode { virtual void toStream(std::ostream& os) const; - virtual Volume& build(const Logger& logger = Acts::getDummyLogger()) = 0; + virtual Volume& build(const Options& options, + const Logger& logger = Acts::getDummyLogger()) = 0; virtual PortalShellBase& connect( - const GeometryContext& gctx, + const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) = 0; - virtual void finalize(TrackingVolume& parent, + virtual void finalize(const Options& options, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) = 0; StaticBlueprintNode& addStaticVolume( diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index cfffd810437..6dc79229168 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -31,13 +31,15 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { void setName(const std::string& name) { m_name = name; } - Volume& build(const Logger& logger = Acts::getDummyLogger()) override; + Volume& build(const Options& options, + const Logger& logger = Acts::getDummyLogger()) override; CylinderStackPortalShell& connect( - const GeometryContext& gctx, + const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(TrackingVolume& parent, const Logger& logger) override; + void finalize(const Options& options, TrackingVolume& parent, + const Logger& logger) override; CylinderContainerBlueprintNode& setDirection(BinningValue direction); CylinderContainerBlueprintNode& setAttachmentStrategy( diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index dc3c615cc30..77e1f42ae2f 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -11,6 +11,7 @@ #include "Acts/Geometry/BlueprintNode.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/GraphViz.hpp" + namespace Acts { class MaterialDesignatorBlueprintNode final : public BlueprintNode { @@ -24,30 +25,32 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { os << "MaterialDesignatorBlueprintNode(" << name() << ")"; } - Volume& build(const Logger& logger = Acts::getDummyLogger()) override { + Volume& build(const Options& options, + const Logger& logger = Acts::getDummyLogger()) override { if (children().size() != 1) { throw std::runtime_error( "MaterialDesignatorBlueprintNode must have exactly one child"); } - return children().at(0).build(logger); + return children().at(0).build(options, logger); } PortalShellBase& connect( - const GeometryContext& gctx, + const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override { if (children().size() != 1) { throw std::runtime_error( "MaterialDesignatorBlueprintNode must have exactly one child"); } - return children().at(0).connect(gctx, logger); + return children().at(0).connect(options, gctx, logger); } - void finalize(TrackingVolume& parent, const Logger& logger) override { + void finalize(const Options& options, TrackingVolume& parent, + const Logger& logger) override { if (children().size() != 1) { throw std::runtime_error( "MaterialDesignatorBlueprintNode must have exactly one child"); } - return children().at(0).finalize(parent, logger); + return children().at(0).finalize(options, parent, logger); } void addToGraphviz(std::ostream& os) const override { diff --git a/Core/include/Acts/Geometry/RootBlueprintNode.hpp b/Core/include/Acts/Geometry/RootBlueprintNode.hpp index 4efc1c18db3..46281cdf9d1 100644 --- a/Core/include/Acts/Geometry/RootBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/RootBlueprintNode.hpp @@ -28,17 +28,18 @@ class RootBlueprintNode : public BlueprintNode { const std::string& name() const override; std::unique_ptr construct( - const GeometryContext& gctx, + const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()); protected: - Volume& build(const Logger& logger = Acts::getDummyLogger()) override; + Volume& build(const Options& options, + const Logger& logger = Acts::getDummyLogger()) override; PortalShellBase& connect( - const GeometryContext& gctx, + const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(TrackingVolume& parent, + void finalize(const Options& options, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override; void addToGraphviz(std::ostream& os) const override; diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index f778bfb858f..a3050530194 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -21,13 +21,14 @@ class StaticBlueprintNode : public BlueprintNode { const std::string& name() const override; - Volume& build(const Logger& logger = Acts::getDummyLogger()) override; + Volume& build(const Options& options, + const Logger& logger = Acts::getDummyLogger()) override; PortalShellBase& connect( - const GeometryContext& gctx, + const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(TrackingVolume& parent, + void finalize(const Options& options, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override; protected: diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index b939c605ebf..b0813b1a4a1 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -46,6 +46,8 @@ std::string BlueprintNode::prefix() const { return indent() + "[" + name() + "]: "; } +void BlueprintNode::Options::validate() const {} + StaticBlueprintNode& BlueprintNode::addStaticVolume( std::unique_ptr volume, const std::function& callback) { diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 5d250d96b4b..a11a598c0cb 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -13,7 +13,7 @@ #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/PortalShell.hpp" #include "Acts/Geometry/TrackingVolume.hpp" -#include "Acts/Navigation/NavigationPolicy.hpp" +#include "Acts/Navigation/INavigationPolicy.hpp" #include "Acts/Utilities/GraphViz.hpp" #include "Acts/Visualization/GeometryView3D.hpp" @@ -35,7 +35,8 @@ const std::string& CylinderContainerBlueprintNode::name() const { return m_name; } -Volume& CylinderContainerBlueprintNode::build(const Logger& logger) { +Volume& CylinderContainerBlueprintNode::build(const Options& options, + const Logger& logger) { ACTS_DEBUG(prefix() << "cylinder container build"); if (m_stack != nullptr) { @@ -44,7 +45,7 @@ Volume& CylinderContainerBlueprintNode::build(const Logger& logger) { } for (auto& child : children()) { - Volume& volume = child.build(logger); + Volume& volume = child.build(options, logger); m_childVolumes.push_back(&volume); // We need to remember which volume we got from which child, so we can // assemble a correct portal shell later @@ -65,7 +66,7 @@ Volume& CylinderContainerBlueprintNode::build(const Logger& logger) { } CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( - const GeometryContext& gctx, const Logger& logger) { + const Options& options, const GeometryContext& gctx, const Logger& logger) { ACTS_DEBUG(prefix() << "Cylinder container connect"); if (m_stack == nullptr) { ACTS_ERROR(prefix() << "Volume is not built"); @@ -105,8 +106,8 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( ACTS_DEBUG(prefix() << " ~> Child (" << child.name() << ") volume: " << volume->volumeBounds()); - CylinderPortalShell* shell = - dynamic_cast(&child.connect(gctx, logger)); + CylinderPortalShell* shell = dynamic_cast( + &child.connect(options, gctx, logger)); if (shell == nullptr) { ACTS_ERROR(prefix() << "Child volume of cylinder stack is not a cylinder"); @@ -142,7 +143,8 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( return *m_shell; } -void CylinderContainerBlueprintNode::finalize(TrackingVolume& parent, +void CylinderContainerBlueprintNode::finalize(const Options& options, + TrackingVolume& parent, const Logger& logger) { ACTS_DEBUG(prefix() << "Finalizing cylinder container"); @@ -170,7 +172,7 @@ void CylinderContainerBlueprintNode::finalize(TrackingVolume& parent, ACTS_DEBUG(prefix() << "Finalizing " << children().size() << " children"); for (auto& child : children()) { - child.finalize(parent, logger); + child.finalize(options, parent, logger); } } diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index 50cdbe081c2..ef0544a5ab8 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -25,16 +25,19 @@ const std::string &RootBlueprintNode::name() const { return root; } -Volume &RootBlueprintNode::build(const Logger & /*logger*/) { +Volume &RootBlueprintNode::build(const Options & /*options*/, + const Logger & /*logger*/) { throw std::logic_error("Root node cannot be built"); } -PortalShellBase &RootBlueprintNode::connect(const GeometryContext & /*gctx*/, +PortalShellBase &RootBlueprintNode::connect(const Options & /*options*/, + const GeometryContext & /*gctx*/, const Logger & /*logger*/) { throw std::logic_error("Root node cannot be connected"); } -void RootBlueprintNode::finalize(TrackingVolume & /*parent*/, +void RootBlueprintNode::finalize(const Options & /*options*/, + TrackingVolume & /*parent*/, const Logger & /*logger*/) { throw std::logic_error("Root node cannot be finalized"); } @@ -48,11 +51,13 @@ void RootBlueprintNode::addToGraphviz(std::ostream &os) const { } std::unique_ptr RootBlueprintNode::construct( - const GeometryContext &gctx, const Logger &logger) { + const Options &options, const GeometryContext &gctx, const Logger &logger) { using enum BinningValue; ACTS_INFO(prefix() << "Building tracking geometry from blueprint tree"); + options.validate(); + if (m_cfg.envelope == ExtentEnvelope::Zero()) { ACTS_WARNING(prefix() << "Root node is configured with zero envelope. This " "might lead to navigation issues"); @@ -66,7 +71,7 @@ std::unique_ptr RootBlueprintNode::construct( auto &child = children().at(0); ACTS_DEBUG(prefix() << "Executing building on tree"); - Volume &topVolume = child.build(logger); + Volume &topVolume = child.build(options, logger); const auto &bounds = topVolume.volumeBounds(); std::stringstream ss; @@ -118,11 +123,11 @@ std::unique_ptr RootBlueprintNode::construct( SingleCylinderPortalShell worldShell{*world}; worldShell.applyToVolume(); - auto &shell = child.connect(gctx, logger); + auto &shell = child.connect(options, gctx, logger); shell.connectOuter(*world); - child.finalize(*world, logger); + child.finalize(options, *world, logger); // @TODO: Handle material decorator, geo id hook diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index 1699aec0609..e44e210e9b6 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -20,7 +20,8 @@ namespace Acts { StaticBlueprintNode::StaticBlueprintNode(std::unique_ptr volume) : m_volume(std::move(volume)) {} -Volume& StaticBlueprintNode::build(const Logger& logger) { +Volume& StaticBlueprintNode::build(const Options& options, + const Logger& logger) { ACTS_DEBUG(prefix() << "static build"); if (!m_volume) { throw std::runtime_error("Volume is not built"); @@ -29,14 +30,15 @@ Volume& StaticBlueprintNode::build(const Logger& logger) { ACTS_DEBUG(prefix() << "Building volume (" << name() << ") with " << children().size() << " children"); for (auto& child : children()) { - child.build(logger); + child.build(options, logger); } ACTS_DEBUG(prefix() << "-> returning volume " << *m_volume); return *m_volume; } -PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, +PortalShellBase& StaticBlueprintNode::connect(const Options& options, + const GeometryContext& gctx, const Logger& logger) { ACTS_DEBUG(prefix() << "Static connect"); if (m_volume == nullptr) { @@ -47,7 +49,7 @@ PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, << children().size() << " children"); for (auto& child : children()) { - auto& shell = child.connect(gctx, logger); + auto& shell = child.connect(options, gctx, logger); // Register ourselves on the outside of the shell shell.connectOuter(*m_volume); } @@ -70,7 +72,8 @@ PortalShellBase& StaticBlueprintNode::connect(const GeometryContext& gctx, return *m_shell; } -void StaticBlueprintNode::finalize(TrackingVolume& parent, +void StaticBlueprintNode::finalize(const Options& options, + TrackingVolume& parent, const Logger& logger) { ACTS_DEBUG(prefix() << "Finalizing static volume"); @@ -85,7 +88,7 @@ void StaticBlueprintNode::finalize(TrackingVolume& parent, } for (auto& child : children()) { - child.finalize(*m_volume, logger); + child.finalize(options, *m_volume, logger); } ACTS_DEBUG(prefix() << "Registering " << m_shell->size() diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 8970a56bad3..c75af7f4809 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -197,7 +197,8 @@ void addBlueprint(Context& ctx) { .def( "build", [](BlueprintNode& self, Logging::Level level) { - return self.build(*getDefaultLogger("Blueprint", level)); + // @TODO: Make options configurable + return self.build({}, *getDefaultLogger("Blueprint", level)); }, py::arg("level") = Logging::INFO); diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index a314b2b140f..b10792f4fcb 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -20,6 +20,7 @@ #include "Acts/Geometry/RootBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Navigation/INavigationPolicy.hpp" #include "Acts/Navigation/NavigationStream.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Visualization/GeometryView3D.hpp" @@ -55,7 +56,7 @@ BOOST_AUTO_TEST_CASE(StaticBlueprintNodeConstruction) { BOOST_CHECK_EQUAL(node->name(), "root"); - BOOST_CHECK_EQUAL(&node->build(), cylPtr); + BOOST_CHECK_EQUAL(&node->build({}), cylPtr); ObjVisualization3D vis; // Add some children @@ -78,7 +79,7 @@ BOOST_AUTO_TEST_CASE(StaticBlueprintNodeConstruction) { std::ofstream ofs{"static.obj"}; vis.write(ofs); - auto tGeometry = root.construct(gctx, *logger); + auto tGeometry = root.construct({}, gctx, *logger); BOOST_REQUIRE(tGeometry); @@ -110,7 +111,7 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { cyl.addStaticVolume(std::move(childCyl)); } - root->construct(gctx, *logger); + root->construct({}, gctx, *logger); } void pseudoNavigation(const TrackingGeometry& trackingGeometry, @@ -331,7 +332,7 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { std::ofstream dot{"api_test_container.dot"}; root->graphViz(dot); - auto trackingGeometry = root->construct(gctx, *logger); + auto trackingGeometry = root->construct({}, gctx, *logger); trackingGeometry->visitVolumes([&](const TrackingVolume* volume) { std::cout << volume->volumeName() << std::endl; @@ -430,7 +431,7 @@ BOOST_AUTO_TEST_CASE(NodeApiTestConfined) { std::ofstream dot{"api_test_confined.dot"}; root->graphViz(dot); - auto trackingGeometry = root->construct(gctx, *logger); + auto trackingGeometry = root->construct({}, gctx, *logger); trackingGeometry->visitVolumes([&](const TrackingVolume* volume) { std::cout << volume->volumeName() << std::endl; From 0b06e2078467a8c3ea172fa2421d8063af4b43fc Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 30 Sep 2024 14:54:14 +0200 Subject: [PATCH 028/100] blueprint: add fallback policy factory --- Core/include/Acts/Geometry/BlueprintNode.hpp | 7 +++++++ Core/src/Geometry/BlueprintNode.cpp | 15 ++++++++++++++- .../Geometry/CylinderContainerBlueprintNode.cpp | 8 +++++--- Core/src/Geometry/RootBlueprintNode.cpp | 4 ++-- Core/src/Geometry/StaticBlueprintNode.cpp | 4 ++-- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index e49ff428977..7bccfacc244 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -33,7 +33,14 @@ class StaticBlueprintNode; class BlueprintNode { public: struct Options { + std::unique_ptr defaultNavigationPolicyFactory{ + makeDefaultNavigationPolicyFactory()}; + void validate() const; + + private: + static std::unique_ptr + makeDefaultNavigationPolicyFactory(); }; BlueprintNode() = default; diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index b0813b1a4a1..f8e5221eb3d 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -11,6 +11,8 @@ #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" +#include "Acts/Navigation/INavigationPolicy.hpp" +#include "Acts/Navigation/TryAllNavigationPolicies.hpp" #include @@ -46,7 +48,18 @@ std::string BlueprintNode::prefix() const { return indent() + "[" + name() + "]: "; } -void BlueprintNode::Options::validate() const {} +void BlueprintNode::Options::validate() const { + if (!defaultNavigationPolicyFactory) { + throw std::invalid_argument("Navigation policy factory is nullptr"); + } +} + +std::unique_ptr +BlueprintNode::Options::makeDefaultNavigationPolicyFactory() { + return NavigationPolicyFactory::make() + .add() + .asUniquePtr(); +} StaticBlueprintNode& BlueprintNode::addStaticVolume( std::unique_ptr volume, diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index a11a598c0cb..29d05c5407b 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -158,13 +158,15 @@ void CylinderContainerBlueprintNode::finalize(const Options& options, throw std::runtime_error("Volume is not connected"); } + // @TODO: Add ability to override this + const auto* policyFactory = options.defaultNavigationPolicyFactory.get(); + ACTS_DEBUG(prefix() << "Registering " << m_gaps.size() << " gap volumes with parent"); for (auto& [shell, gap] : m_gaps) { std::cout << "~> " << gap->volumeName() << std::endl; - // @TODO: This needs to become configurable - gap->setNavigationPolicy( - std::make_unique(*gap)); + gap->setNavigationPolicy(policyFactory->build(*gap)); + parent.addVolume(std::move(gap)); shell->applyToVolume(); } diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index ef0544a5ab8..1cfb41a90df 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -13,7 +13,7 @@ #include "Acts/Geometry/Extent.hpp" #include "Acts/Geometry/PortalShell.hpp" #include "Acts/Geometry/VolumeBounds.hpp" -#include "Acts/Navigation/NavigationPolicy.hpp" +#include "Acts/Navigation/INavigationPolicy.hpp" #include "Acts/Utilities/GraphViz.hpp" namespace Acts { @@ -117,7 +117,7 @@ std::unique_ptr RootBlueprintNode::construct( // @TODO: This needs to become configurable world->setNavigationPolicy( - std::make_unique(*world)); + options.defaultNavigationPolicyFactory->build(*world)); // Need one-sided portal shell that connects outwards to nullptr SingleCylinderPortalShell worldShell{*world}; diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index e44e210e9b6..8602be1fb07 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -11,7 +11,7 @@ #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/PortalShell.hpp" #include "Acts/Geometry/VolumeBounds.hpp" -#include "Acts/Navigation/NavigationPolicy.hpp" +#include "Acts/Navigation/INavigationPolicy.hpp" #include "Acts/Utilities/GraphViz.hpp" #include "Acts/Visualization/GeometryView3D.hpp" @@ -100,7 +100,7 @@ void StaticBlueprintNode::finalize(const Options& options, // @TODO: This needs to become configurable m_volume->setNavigationPolicy( - std::make_unique(*m_volume)); + options.defaultNavigationPolicyFactory->build(*m_volume)); parent.addVolume(std::move(m_volume)); } From c1de40d5f290a5e487cfb0698107749481dcf929 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 1 Oct 2024 10:25:20 +0200 Subject: [PATCH 029/100] blueprint: Add geo context to build call --- Core/include/Acts/Geometry/BlueprintNode.hpp | 2 +- .../include/Acts/Geometry/CylinderContainerBlueprintNode.hpp | 2 +- .../Acts/Geometry/MaterialDesignatorBlueprintNode.hpp | 4 ++-- Core/include/Acts/Geometry/RootBlueprintNode.hpp | 5 +++-- Core/include/Acts/Geometry/StaticBlueprintNode.hpp | 3 ++- Core/src/Geometry/CylinderContainerBlueprintNode.cpp | 3 ++- Core/src/Geometry/RootBlueprintNode.cpp | 3 ++- Core/src/Geometry/StaticBlueprintNode.cpp | 3 ++- Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp | 2 +- 9 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index 7bccfacc244..3b0b85558ef 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -51,7 +51,7 @@ class BlueprintNode { virtual void toStream(std::ostream& os) const; - virtual Volume& build(const Options& options, + virtual Volume& build(const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) = 0; virtual PortalShellBase& connect( diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index 6dc79229168..6faca235401 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -31,7 +31,7 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { void setName(const std::string& name) { m_name = name; } - Volume& build(const Options& options, + Volume& build(const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; CylinderStackPortalShell& connect( diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index 77e1f42ae2f..fed6cff4d7b 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -25,13 +25,13 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { os << "MaterialDesignatorBlueprintNode(" << name() << ")"; } - Volume& build(const Options& options, + Volume& build(const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override { if (children().size() != 1) { throw std::runtime_error( "MaterialDesignatorBlueprintNode must have exactly one child"); } - return children().at(0).build(options, logger); + return children().at(0).build(options, gctx, logger); } PortalShellBase& connect( diff --git a/Core/include/Acts/Geometry/RootBlueprintNode.hpp b/Core/include/Acts/Geometry/RootBlueprintNode.hpp index 46281cdf9d1..39afdb22467 100644 --- a/Core/include/Acts/Geometry/RootBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/RootBlueprintNode.hpp @@ -9,13 +9,14 @@ #pragma once #include "Acts/Geometry/BlueprintNode.hpp" -#include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/PortalShell.hpp" #include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Geometry/TrackingVolume.hpp" namespace Acts { +class GeometryContext; + class RootBlueprintNode : public BlueprintNode { public: struct Config { @@ -32,7 +33,7 @@ class RootBlueprintNode : public BlueprintNode { const Logger& logger = Acts::getDummyLogger()); protected: - Volume& build(const Options& options, + Volume& build(const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; PortalShellBase& connect( diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index a3050530194..60528ab3830 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -21,7 +21,8 @@ class StaticBlueprintNode : public BlueprintNode { const std::string& name() const override; - Volume& build(const Options& options, + Volume& build(const Options& options, const GeometryContext& gctx, + const Logger& logger = Acts::getDummyLogger()) override; PortalShellBase& connect( diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 29d05c5407b..4872465012e 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -36,6 +36,7 @@ const std::string& CylinderContainerBlueprintNode::name() const { } Volume& CylinderContainerBlueprintNode::build(const Options& options, + const GeometryContext& gctx, const Logger& logger) { ACTS_DEBUG(prefix() << "cylinder container build"); @@ -45,7 +46,7 @@ Volume& CylinderContainerBlueprintNode::build(const Options& options, } for (auto& child : children()) { - Volume& volume = child.build(options, logger); + Volume& volume = child.build(options, gctx, logger); m_childVolumes.push_back(&volume); // We need to remember which volume we got from which child, so we can // assemble a correct portal shell later diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index 1cfb41a90df..92753610024 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -26,6 +26,7 @@ const std::string &RootBlueprintNode::name() const { } Volume &RootBlueprintNode::build(const Options & /*options*/, + const GeometryContext & /*gctx*/, const Logger & /*logger*/) { throw std::logic_error("Root node cannot be built"); } @@ -71,7 +72,7 @@ std::unique_ptr RootBlueprintNode::construct( auto &child = children().at(0); ACTS_DEBUG(prefix() << "Executing building on tree"); - Volume &topVolume = child.build(options, logger); + Volume &topVolume = child.build(options, gctx, logger); const auto &bounds = topVolume.volumeBounds(); std::stringstream ss; diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index 8602be1fb07..fb12108047a 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -21,6 +21,7 @@ StaticBlueprintNode::StaticBlueprintNode(std::unique_ptr volume) : m_volume(std::move(volume)) {} Volume& StaticBlueprintNode::build(const Options& options, + const GeometryContext& gctx, const Logger& logger) { ACTS_DEBUG(prefix() << "static build"); if (!m_volume) { @@ -30,7 +31,7 @@ Volume& StaticBlueprintNode::build(const Options& options, ACTS_DEBUG(prefix() << "Building volume (" << name() << ") with " << children().size() << " children"); for (auto& child : children()) { - child.build(options, logger); + child.build(options, gctx, logger); } ACTS_DEBUG(prefix() << "-> returning volume " << *m_volume); diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index b10792f4fcb..fa3a675eea1 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -56,7 +56,7 @@ BOOST_AUTO_TEST_CASE(StaticBlueprintNodeConstruction) { BOOST_CHECK_EQUAL(node->name(), "root"); - BOOST_CHECK_EQUAL(&node->build({}), cylPtr); + BOOST_CHECK_EQUAL(&node->build({}, gctx), cylPtr); ObjVisualization3D vis; // Add some children From 3e9e275ea7e9ae9ccb42367e5b53375ab39fca82 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 1 Oct 2024 15:18:19 +0200 Subject: [PATCH 030/100] blueprint: Minimal Layer node + basic test --- Core/include/Acts/Geometry/BlueprintNode.hpp | 5 + .../Acts/Geometry/LayerBlueprintNode.hpp | 55 +++++++ Core/src/Geometry/BlueprintNode.cpp | 12 ++ Core/src/Geometry/CMakeLists.txt | 1 + Core/src/Geometry/LayerBlueprintNode.cpp | 154 ++++++++++++++++++ .../Core/Geometry/BlueprintNodeTests.cpp | 74 +++++++++ 6 files changed, 301 insertions(+) create mode 100644 Core/include/Acts/Geometry/LayerBlueprintNode.hpp create mode 100644 Core/src/Geometry/LayerBlueprintNode.cpp diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index 3b0b85558ef..e42e2e4b95e 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -29,6 +29,7 @@ class PortalShellBase; class CylinderContainerBlueprintNode; class MaterialDesignatorBlueprintNode; class StaticBlueprintNode; +class LayerBlueprintNode; class BlueprintNode { public: @@ -79,6 +80,10 @@ class BlueprintNode { const std::function& callback = {}); + LayerBlueprintNode& addLayer( + const std::string& name, + const std::function& callback = {}); + BlueprintNode& addChild(std::shared_ptr child); using MutableChildRange = diff --git a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp new file mode 100644 index 00000000000..4cbe60762c4 --- /dev/null +++ b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp @@ -0,0 +1,55 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Geometry/StaticBlueprintNode.hpp" + +#include + +namespace Acts { + +class LayerBlueprintNode : public StaticBlueprintNode { + public: + enum class LayerType { Cylinder, Disc, Plane }; + + LayerBlueprintNode(const std::string& name) + : StaticBlueprintNode{nullptr}, m_name(name) {} + + const std::string& name() const override; + + Volume& build(const Options& options, const GeometryContext& gctx, + const Logger& logger = Acts::getDummyLogger()) override; + + void finalize(const Options& options, TrackingVolume& parent, + const Logger& logger = Acts::getDummyLogger()) override; + + LayerBlueprintNode& setSurfaces( + std::vector> surfaces); + + LayerBlueprintNode& setTransform(const Transform3& transform); + + LayerBlueprintNode& setEnvelope(const ExtentEnvelope& envelope); + + LayerBlueprintNode& setLayerType(LayerType layerType); + + void addToGraphviz(std::ostream& os) const override; + + private: + void buildVolume(const Extent& extent, const Logger& logger); + + std::string m_name; + std::vector> m_surfaces{}; + Transform3 m_transform = Transform3::Identity(); + ExtentEnvelope m_envelope = ExtentEnvelope::Zero(); + LayerType m_layerType = LayerType::Cylinder; +}; + +std::ostream& operator<<(std::ostream& os, LayerBlueprintNode::LayerType type); + +} // namespace Acts diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index f8e5221eb3d..37a14b8d94d 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -9,6 +9,7 @@ #include "Acts/Geometry/BlueprintNode.hpp" #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" +#include "Acts/Geometry/LayerBlueprintNode.hpp" #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Navigation/INavigationPolicy.hpp" @@ -110,6 +111,17 @@ MaterialDesignatorBlueprintNode& BlueprintNode::addMaterial( return *material; } +LayerBlueprintNode& BlueprintNode::addLayer( + const std::string& name, + const std::function& callback) { + auto layer = std::make_shared(name); + addChild(layer); + if (callback) { + callback(*layer); + } + return *layer; +} + void BlueprintNode::graphViz(std::ostream& os) const { os << "digraph BlueprintNode {" << std::endl; addToGraphviz(os); diff --git a/Core/src/Geometry/CMakeLists.txt b/Core/src/Geometry/CMakeLists.txt index 3b98209ff74..5c0454ceac2 100644 --- a/Core/src/Geometry/CMakeLists.txt +++ b/Core/src/Geometry/CMakeLists.txt @@ -47,5 +47,6 @@ target_sources( RootBlueprintNode.cpp CylinderContainerBlueprintNode.cpp StaticBlueprintNode.cpp + LayerBlueprintNode.cpp Blueprint.cpp ) diff --git a/Core/src/Geometry/LayerBlueprintNode.cpp b/Core/src/Geometry/LayerBlueprintNode.cpp new file mode 100644 index 00000000000..1b674396d77 --- /dev/null +++ b/Core/src/Geometry/LayerBlueprintNode.cpp @@ -0,0 +1,154 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Geometry/LayerBlueprintNode.hpp" + +#include "Acts/Definitions/Algebra.hpp" +#include "Acts/Geometry/CuboidVolumeBounds.hpp" +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/ProtoLayer.hpp" +#include "Acts/Geometry/VolumeBounds.hpp" +#include "Acts/Utilities/GraphViz.hpp" + +namespace Acts { + +Volume& LayerBlueprintNode::build(const BlueprintNode::Options& options, + const GeometryContext& gctx, + const Logger& logger) { + if (m_surfaces.empty()) { + ACTS_ERROR("LayerBlueprintNode: no surfaces provided"); + throw std::invalid_argument("LayerBlueprintNode: no surfaces provided"); + } + + ACTS_DEBUG(prefix() << "Building Layer " << name() << " from " + << m_surfaces.size() << " surfaces"); + ACTS_VERBOSE(prefix() << " -> layer type: " << m_layerType); + ACTS_VERBOSE(prefix() << " -> transform:\n" << m_transform.matrix()); + + Extent extent; + + ProtoLayer protoLayer{gctx, m_surfaces, m_transform.inverse()}; + ACTS_VERBOSE(prefix() << "Built proto layer: " << protoLayer); + + extent.addConstrain(protoLayer.extent, m_envelope); + + ACTS_VERBOSE(prefix() << " -> layer extent: " << extent); + + buildVolume(extent, logger); + assert(m_volume != nullptr && "Volume not built from proto layer"); + + for (auto& surface : m_surfaces) { + m_volume->addSurface(surface); + } + + return StaticBlueprintNode::build(options, gctx, logger); +} + +void LayerBlueprintNode::buildVolume(const Extent& extent, + const Logger& logger) { + ACTS_VERBOSE(prefix() << "Building volume for layer " << name()); + using enum BinningValue; + using enum LayerType; + + std::shared_ptr bounds; + switch (m_layerType) { + case Cylinder: + case Disc: { + ActsScalar minR = extent.min(binR); + ActsScalar maxR = extent.max(binR); + ActsScalar hlZ = extent.interval(binZ) / 2.0; + bounds = std::make_shared(minR, maxR, hlZ); + break; + } + case Plane: { + ActsScalar hlX = extent.interval(binX) / 2.0; + ActsScalar hlY = extent.interval(binY) / 2.0; + ActsScalar hlZ = extent.interval(binZ) / 2.0; + bounds = std::make_shared(hlX, hlY, hlZ); + break; + } + } + + assert(bounds != nullptr); + + ACTS_VERBOSE(prefix() << " -> bounds: " << *bounds); + + Transform3 transform = m_transform; + transform.translation() = + Vector3{extent.medium(binX), extent.medium(binY), extent.medium(binZ)}; + + ACTS_VERBOSE(prefix() << " -> adjusted transform:\n" << transform.matrix()); + + m_volume = + std::make_unique(transform, std::move(bounds), m_name); +} + +void LayerBlueprintNode::finalize(const BlueprintNode::Options& options, + TrackingVolume& parent, + const Logger& logger) { + StaticBlueprintNode::finalize(options, parent, logger); +} + +const std::string& LayerBlueprintNode::name() const { + return m_name; +} + +LayerBlueprintNode& LayerBlueprintNode::setSurfaces( + std::vector> surfaces) { + m_surfaces = std::move(surfaces); + return *this; +} + +LayerBlueprintNode& LayerBlueprintNode::setTransform( + const Transform3& transform) { + m_transform = transform; + return *this; +} + +LayerBlueprintNode& LayerBlueprintNode::setEnvelope( + const ExtentEnvelope& envelope) { + m_envelope = envelope; + return *this; +} + +LayerBlueprintNode& LayerBlueprintNode::setLayerType(LayerType layerType) { + m_layerType = layerType; + return *this; +} + +void LayerBlueprintNode::addToGraphviz(std::ostream& os) const { + std::stringstream ss; + ss << "" << name() << ""; + ss << "
"; + ss << m_layerType; + + GraphViz::Node node{ + .id = name(), .label = ss.str(), .shape = GraphViz::Shape::Diamond}; + + os << node; + + BlueprintNode::addToGraphviz(os); +} + +std::ostream& operator<<(std::ostream& os, LayerBlueprintNode::LayerType type) { + switch (type) { + using enum LayerBlueprintNode::LayerType; + case Cylinder: + os << "Cylinder"; + break; + case Disc: + os << "Disc"; + break; + case Plane: + os << "Plane"; + break; + } + return os; +} + +} // namespace Acts diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index fa3a675eea1..a022c88ca47 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -16,12 +16,15 @@ #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/CylinderVolumeBounds.hpp" #include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/LayerBlueprintNode.hpp" #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/RootBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Geometry/TrackingVolume.hpp" #include "Acts/Navigation/INavigationPolicy.hpp" #include "Acts/Navigation/NavigationStream.hpp" +#include "Acts/Surfaces/RectangleBounds.hpp" +#include "Acts/Tests/CommonHelpers/DetectorElementStub.hpp" #include "Acts/Utilities/Logger.hpp" #include "Acts/Visualization/GeometryView3D.hpp" #include "Acts/Visualization/ObjVisualization3D.hpp" @@ -455,6 +458,77 @@ BOOST_AUTO_TEST_CASE(NodeApiTestConfined) { BOOST_CHECK_EQUAL(wrapper->volumes().size(), 4); } +BOOST_AUTO_TEST_CASE(LayerNode) { + double yrot = 45_degree; + Transform3 base = Transform3::Identity() * AngleAxis3{yrot, Vector3::UnitY()}; + + auto recBounds = std::make_shared(3_mm, 6_mm); + + std::vector> detectorElements; + + auto makeFan = [&](double thickness = 0) { + detectorElements.clear(); + + std::size_t nSensors = 8; + double deltaPhi = 2 * M_PI / nSensors; + double r = 20_mm; + std::vector> surfaces; + for (std::size_t i = 0; i < nSensors; i++) { + // Create a fan of sensors + + Transform3 trf = base * AngleAxis3{deltaPhi * i, Vector3::UnitZ()} * + Translation3(Vector3::UnitX() * r); + + auto& element = detectorElements.emplace_back( + std::make_unique(trf, recBounds, thickness)); + + element->surface().assignDetectorElement(*element); + + surfaces.push_back(element->surface().getSharedPtr()); + } + return surfaces; + }; + + std::vector> surfaces = makeFan(2.5_mm); + + RootBlueprintNode root{{.envelope{{ + .z = {2_mm, 2_mm}, + .r = {3_mm, 5_mm}, + }}}}; + + root.addLayer("Layer0", [&](auto& layer) { + layer.setSurfaces(surfaces) + .setLayerType(LayerBlueprintNode::LayerType::Disc) + .setEnvelope(ExtentEnvelope{{ + .z = {0.1_mm, 0.1_mm}, + .r = {1_mm, 1_mm}, + }}) + .setTransform(base); + }); + + std::ofstream dot{"layer_node.dot"}; + root.graphViz(dot); + + auto trackingGeometry = + root.construct({}, gctx, *logger->clone(std::nullopt, Logging::VERBOSE)); + + ObjVisualization3D vis; + + trackingGeometry->visualize(vis, gctx, {}, {}); + + vis.write("layer_node.obj"); + + std::size_t nSurfaces = 0; + + trackingGeometry->visitSurfaces([&](const Surface* surface) { + if (surface->associatedDetectorElement() != nullptr) { + nSurfaces++; + } + }); + + BOOST_CHECK_EQUAL(nSurfaces, surfaces.size()); +} + BOOST_AUTO_TEST_SUITE_END(); BOOST_AUTO_TEST_SUITE_END(); From 5c2effeaf85bdcd9c5e13de9a6b07cc6f125025f Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 1 Oct 2024 10:25:20 +0200 Subject: [PATCH 031/100] blueprint: Add geo context to build call --- Examples/Python/src/Blueprint.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index c75af7f4809..dad23a29c8a 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -196,11 +196,13 @@ void addBlueprint(Context& ctx) { }) .def( "build", - [](BlueprintNode& self, Logging::Level level) { + [](BlueprintNode& self, const GeometryContext& gctx, + Logging::Level level) { // @TODO: Make options configurable - return self.build({}, *getDefaultLogger("Blueprint", level)); + return self.build({}, gctx, + *getDefaultLogger("Blueprint", level)); }, - py::arg("level") = Logging::INFO); + py::arg("gctx"), py::arg("level") = Logging::INFO); py::class_(blueprintNode, "MutableChildRange") From 0ce0dca858a0ea635c3e395d6b9c6f5fd389cc0a Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 1 Oct 2024 16:52:55 +0200 Subject: [PATCH 032/100] blueprint: Improve verbosity of test --- .../Core/Geometry/BlueprintNodeTests.cpp | 55 +++++++++---------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index a022c88ca47..8e90e50d1b5 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -120,7 +120,7 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { void pseudoNavigation(const TrackingGeometry& trackingGeometry, Vector3 position, const Vector3& direction, std::ostream& csv, std::size_t run, - std::size_t substepsPerCm = 1) { + std::size_t substepsPerCm, const Logger& logger) { std::mt19937 rng{static_cast(run)}; std::uniform_real_distribution<> dist{0.01, 0.99}; @@ -136,7 +136,7 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, csv << "," << volume->geometryId().boundary(); csv << std::endl; - std::cout << "start pseudo navigation" << std::endl; + ACTS_VERBOSE("start pseudo navigation"); for (std::size_t i = 0; i < 100; i++) { main = NavigationStream{}; @@ -144,28 +144,26 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, currentVolume->updateNavigationState( {.main = main, .position = position, .direction = direction}); - std::cout << main.candidates().size() << " candidates" << std::endl; + ACTS_VERBOSE(main.candidates().size() << " candidates"); for (const auto& candidate : main.candidates()) { - std::cout << " -> " << candidate.surface().geometryId() << std::endl; - std::cout << " " << candidate.surface().toStream(gctx) << std::endl; + ACTS_VERBOSE(" -> " << candidate.surface().geometryId()); + ACTS_VERBOSE(" " << candidate.surface().toStream(gctx)); } - std::cout << "initializing candidates" << std::endl; + ACTS_VERBOSE("initializing candidates"); main.initialize(gctx, {position, direction}, BoundaryTolerance::None()); - std::cout << main.candidates().size() << " candidates remaining" - << std::endl; + ACTS_VERBOSE(main.candidates().size() << " candidates remaining"); for (const auto& candidate : main.candidates()) { - std::cout << " -> " << candidate.surface().geometryId() << std::endl; - std::cout << " " << candidate.surface().toStream(gctx) << std::endl; + ACTS_VERBOSE(" -> " << candidate.surface().geometryId()); + ACTS_VERBOSE(" " << candidate.surface().toStream(gctx)); } if (main.currentCandidate().surface().isOnSurface(gctx, position, direction)) { - std::cout << "Already on portal at initialization, skipping candidate" - << std::endl; + ACTS_VERBOSE("Already on portal at initialization, skipping candidate"); auto id = main.currentCandidate().surface().geometryId(); csv << run << "," << position[0] << "," << position[1] << "," @@ -174,22 +172,22 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, csv << "," << id.boundary(); csv << std::endl; if (!main.switchToNextCandidate()) { - std::cout << "candidates exhausted unexpectedly" << std::endl; + ACTS_WARNING("candidates exhausted unexpectedly"); break; } } const auto& candidate = main.currentCandidate(); - std::cout << candidate.portal << std::endl; - std::cout << candidate.intersection.position().transpose() << std::endl; + ACTS_VERBOSE(candidate.portal); + ACTS_VERBOSE(candidate.intersection.position().transpose()); BOOST_REQUIRE_NE(candidate.portal, nullptr); - std::cout << "on portal: " << candidate.portal->surface().geometryId() - << std::endl; + ACTS_VERBOSE("on portal: " << candidate.portal->surface().geometryId()); - std::cout << "moving to position: " << position.transpose() - << " (r=" << VectorHelpers::perp(position) << ")\n"; + ACTS_VERBOSE("moving to position: " << position.transpose() << " (r=" + << VectorHelpers::perp(position) + << ")"); Vector3 delta = candidate.intersection.position() - position; std::size_t substeps = @@ -206,20 +204,21 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, position = candidate.intersection.position(); - std::cout << " -> " << position.transpose() - << " (r=" << VectorHelpers::perp(position) << ")" << std::endl; + ACTS_VERBOSE(" -> " + << position.transpose() + << " (r=" << VectorHelpers::perp(position) << ")"); currentVolume = candidate.portal->resolveVolume(gctx, position, direction).value(); if (currentVolume == nullptr) { - std::cout << "switched to nullptr" << std::endl; + ACTS_VERBOSE("switched to nullptr"); break; } - std::cout << "switched to " << currentVolume->volumeName() << std::endl; + ACTS_VERBOSE("switched to " << currentVolume->volumeName()); - std::cout << "-----" << std::endl; + ACTS_VERBOSE("-----"); } } @@ -365,9 +364,6 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { using namespace Acts::UnitLiterals; for (std::size_t i = 0; i < 5000; i++) { - // double eta = 1.0; - // double theta = 2 * std::atan(std::exp(-eta)); - double theta = thetaDist(rnd); double phi = 2 * M_PI * dist(rnd); @@ -380,11 +376,10 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { std::cout << "dir: " << direction.transpose() << std::endl; std::cout << direction.norm() << std::endl; - pseudoNavigation(*trackingGeometry, position, direction, csv, i, 2); + pseudoNavigation(*trackingGeometry, position, direction, csv, i, 2, + *logger->clone(std::nullopt, Logging::DEBUG)); // portalSamples(*trackingGeometry, position, direction, csv, i); - - // break; } } From f68ec4fbece90e381522ce66a69f4436b440887d Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 1 Oct 2024 17:19:57 +0200 Subject: [PATCH 033/100] blueprint: Complex geo with surfaces (no navigation yet) --- .../Core/Geometry/BlueprintNodeTests.cpp | 107 +++++++++++------- 1 file changed, 69 insertions(+), 38 deletions(-) diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index 8e90e50d1b5..c04d1d81732 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -30,6 +30,7 @@ #include "Acts/Visualization/ObjVisualization3D.hpp" #include +#include using namespace Acts::UnitLiterals; @@ -39,6 +40,34 @@ auto logger = Acts::getDefaultLogger("UnitTests", Acts::Logging::DEBUG); GeometryContext gctx; +inline std::vector> makeFanLayer( + const Transform3& base, + std::vector>& elements, + double r = 300_mm, std::size_t nSensors = 8, double thickness = 0) { + auto recBounds = std::make_shared(40_mm, 60_mm); + + double deltaPhi = 2 * M_PI / nSensors; + std::vector> surfaces; + for (std::size_t i = 0; i < nSensors; i++) { + // Create a fan of sensors + + Transform3 trf = base * AngleAxis3{deltaPhi * i, Vector3::UnitZ()} * + Translation3(Vector3::UnitX() * r); + + if (i % 2 == 0) { + trf = trf * Translation3{Vector3::UnitZ() * 5_mm}; + } + + auto& element = elements.emplace_back( + std::make_unique(trf, recBounds, thickness)); + + element->surface().assignDetectorElement(*element); + + surfaces.push_back(element->surface().getSharedPtr()); + } + return surfaces; +} + BOOST_AUTO_TEST_SUITE(Geometry); BOOST_AUTO_TEST_SUITE(BlueprintNodeTest); @@ -121,12 +150,16 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, Vector3 position, const Vector3& direction, std::ostream& csv, std::size_t run, std::size_t substepsPerCm, const Logger& logger) { + ACTS_VERBOSE("start navigation " << run); + ACTS_VERBOSE("dir: " << direction.transpose()); + ACTS_VERBOSE(direction.norm()); + std::mt19937 rng{static_cast(run)}; std::uniform_real_distribution<> dist{0.01, 0.99}; const auto* volume = trackingGeometry.lowestTrackingVolume(gctx, position); BOOST_REQUIRE_NE(volume, nullptr); - std::cout << volume->volumeName() << std::endl; + ACTS_VERBOSE(volume->volumeName()); NavigationStream main; const TrackingVolume* currentVolume = volume; @@ -261,6 +294,12 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { // Transform3 base{AngleAxis3{30_degree, Vector3{1, 0, 0}}}; Transform3 base{Transform3::Identity()}; + std::vector> detectorElements; + auto makeFan = [&](const Transform3& layerBase, auto&&..., double r, + std::size_t nSensors, double thickness) { + return makeFanLayer(layerBase, detectorElements, r, nSensors, thickness); + }; + RootBlueprintNode::Config cfg; cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; cfg.envelope[BinningValue::binR] = {0_mm, 20_mm}; @@ -277,15 +316,31 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { ec.setAttachmentStrategy( CylinderVolumeStack::AttachmentStrategy::Gap); - ec.addStaticVolume( - base * Translation3{Vector3{0, 0, -600_mm}}, - std::make_shared(200_mm, 450_mm, 20_mm), - "PixelNeg1"); - - ec.addStaticVolume( - base * Translation3{Vector3{0, 0, -400_mm}}, - std::make_shared(200_mm, 800_mm, 20_mm), - "PixelNeg2"); + auto makeLayer = [&](const Transform3& trf, auto& layer) { + std::vector> surfaces; + auto layerSurfaces = makeFan(trf, 300_mm, 10, 2_mm); + std::copy(layerSurfaces.begin(), layerSurfaces.end(), + std::back_inserter(surfaces)); + layerSurfaces = makeFan(trf, 500_mm, 16, 2_mm); + std::copy(layerSurfaces.begin(), layerSurfaces.end(), + std::back_inserter(surfaces)); + + layer.setSurfaces(surfaces) + .setLayerType(LayerBlueprintNode::LayerType::Disc) + .setEnvelope(ExtentEnvelope{{ + .z = {5_mm, 5_mm}, + .r = {10_mm, 20_mm}, + }}) + .setTransform(base); + }; + + ec.addLayer("PixelNeg1", [&](auto& layer) { + makeLayer(base * Translation3{Vector3{0, 0, -600_mm}}, layer); + }); + + ec.addLayer("PixelNeg2", [&](auto& layer) { + makeLayer(base * Translation3{Vector3{0, 0, -400_mm}}, layer); + }); }); cyl.addCylinderContainer( @@ -363,7 +418,7 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { using namespace Acts::UnitLiterals; - for (std::size_t i = 0; i < 5000; i++) { + for (std::size_t i = 0; i < 5; i++) { double theta = thetaDist(rnd); double phi = 2 * M_PI * dist(rnd); @@ -372,12 +427,8 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { direction[1] = std::sin(theta) * std::sin(phi); direction[2] = std::cos(theta); - std::cout << "start navigation " << i << std::endl; - std::cout << "dir: " << direction.transpose() << std::endl; - std::cout << direction.norm() << std::endl; - pseudoNavigation(*trackingGeometry, position, direction, csv, i, 2, - *logger->clone(std::nullopt, Logging::DEBUG)); + *logger->clone(std::nullopt, Logging::VERBOSE)); // portalSamples(*trackingGeometry, position, direction, csv, i); } @@ -457,31 +508,11 @@ BOOST_AUTO_TEST_CASE(LayerNode) { double yrot = 45_degree; Transform3 base = Transform3::Identity() * AngleAxis3{yrot, Vector3::UnitY()}; - auto recBounds = std::make_shared(3_mm, 6_mm); - std::vector> detectorElements; - auto makeFan = [&](double thickness = 0) { + auto makeFan = [&](double thickness) { detectorElements.clear(); - - std::size_t nSensors = 8; - double deltaPhi = 2 * M_PI / nSensors; - double r = 20_mm; - std::vector> surfaces; - for (std::size_t i = 0; i < nSensors; i++) { - // Create a fan of sensors - - Transform3 trf = base * AngleAxis3{deltaPhi * i, Vector3::UnitZ()} * - Translation3(Vector3::UnitX() * r); - - auto& element = detectorElements.emplace_back( - std::make_unique(trf, recBounds, thickness)); - - element->surface().assignDetectorElement(*element); - - surfaces.push_back(element->surface().getSharedPtr()); - } - return surfaces; + return makeFanLayer(base, detectorElements, thickness); }; std::vector> surfaces = makeFan(2.5_mm); From 59996d68968e20e0c3fa8bb070621cd5f18e8685 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 2 Oct 2024 09:26:37 +0200 Subject: [PATCH 034/100] blueprint: Add barrel layers --- .../Core/Geometry/BlueprintNodeTests.cpp | 224 +++++++++++++----- 1 file changed, 169 insertions(+), 55 deletions(-) diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index c04d1d81732..77596a4ea3d 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -68,6 +68,37 @@ inline std::vector> makeFanLayer( return surfaces; } +inline std::vector> makeBarrelLayer( + const Transform3& base, + std::vector>& elements, + double r = 300_mm, std::size_t nStaves = 10, int nSensorsPerStave = 8, + double thickness = 0, double hlPhi = 40_mm, double hlZ = 60_mm) { + auto recBounds = std::make_shared(hlPhi, hlZ); + + double deltaPhi = 2 * M_PI / nStaves; + std::vector> surfaces; + + for (std::size_t istave = 0; istave < nStaves; istave++) { + for (int isensor = -nSensorsPerStave; isensor <= nSensorsPerStave; + isensor++) { + double z = isensor * (2 * hlZ + 5_mm); + + Transform3 trf = base * Translation3(Vector3::UnitZ() * z) * + AngleAxis3{deltaPhi * istave, Vector3::UnitZ()} * + Translation3(Vector3::UnitX() * r) * + AngleAxis3{10_degree, Vector3::UnitZ()} * + AngleAxis3{90_degree, Vector3::UnitY()} * + AngleAxis3{90_degree, Vector3::UnitZ()}; + auto& element = elements.emplace_back( + std::make_unique(trf, recBounds, thickness)); + element->surface().assignDetectorElement(*element); + surfaces.push_back(element->surface().getSharedPtr()); + } + } + + return surfaces; +} + BOOST_AUTO_TEST_SUITE(Geometry); BOOST_AUTO_TEST_SUITE(BlueprintNodeTest); @@ -167,6 +198,7 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, csv << run << "," << position[0] << "," << position[1] << "," << position[2]; csv << "," << volume->geometryId().volume(); csv << "," << volume->geometryId().boundary(); + csv << "," << volume->geometryId().sensitive(); csv << std::endl; ACTS_VERBOSE("start pseudo navigation"); @@ -196,13 +228,14 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, if (main.currentCandidate().surface().isOnSurface(gctx, position, direction)) { - ACTS_VERBOSE("Already on portal at initialization, skipping candidate"); + ACTS_VERBOSE("Already on surface at initialization, skipping candidate"); auto id = main.currentCandidate().surface().geometryId(); csv << run << "," << position[0] << "," << position[1] << "," << position[2]; csv << "," << id.volume(); csv << "," << id.boundary(); + csv << "," << id.sensitive(); csv << std::endl; if (!main.switchToNextCandidate()) { ACTS_WARNING("candidates exhausted unexpectedly"); @@ -210,42 +243,69 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, } } - const auto& candidate = main.currentCandidate(); - ACTS_VERBOSE(candidate.portal); - ACTS_VERBOSE(candidate.intersection.position().transpose()); + auto writeIntersection = [&](const Vector3& position, + const Surface& surface) { + csv << run << "," << position[0] << "," << position[1] << "," + << position[2]; + csv << "," << surface.geometryId().volume(); + csv << "," << surface.geometryId().boundary(); + csv << "," << surface.geometryId().sensitive(); + csv << std::endl; + }; + + bool terminated = false; + while (main.remainingCandidates() > 0) { + const auto& candidate = main.currentCandidate(); - BOOST_REQUIRE_NE(candidate.portal, nullptr); + ACTS_VERBOSE(candidate.portal); + ACTS_VERBOSE(candidate.intersection.position().transpose()); - ACTS_VERBOSE("on portal: " << candidate.portal->surface().geometryId()); + ACTS_VERBOSE("moving to position: " << position.transpose() << " (r=" + << VectorHelpers::perp(position) + << ")"); - ACTS_VERBOSE("moving to position: " << position.transpose() << " (r=" - << VectorHelpers::perp(position) - << ")"); - Vector3 delta = candidate.intersection.position() - position; + Vector3 delta = candidate.intersection.position() - position; - std::size_t substeps = - std::max(1l, std::lround(delta.norm() / 10_cm * substepsPerCm)); + std::size_t substeps = + std::max(1l, std::lround(delta.norm() / 10_cm * substepsPerCm)); - for (std::size_t j = 0; j < substeps; j++) { - // position += delta / (substeps + 1); - Vector3 subpos = position + dist(rng) * delta; - csv << run << "," << subpos[0] << "," << subpos[1] << "," << subpos[2]; - csv << "," << currentVolume->geometryId().volume(); - csv << "," << currentVolume->geometryId().boundary(); - csv << std::endl; - } + for (std::size_t j = 0; j < substeps; j++) { + // position += delta / (substeps + 1); + Vector3 subpos = position + dist(rng) * delta; + csv << run << "," << subpos[0] << "," << subpos[1] << "," << subpos[2]; + csv << "," << currentVolume->geometryId().volume(); + csv << ",0,0"; // zero boundary and sensitive ids + csv << std::endl; + } - position = candidate.intersection.position(); + position = candidate.intersection.position(); + ACTS_VERBOSE(" -> " + << position.transpose() + << " (r=" << VectorHelpers::perp(position) << ")"); - ACTS_VERBOSE(" -> " - << position.transpose() - << " (r=" << VectorHelpers::perp(position) << ")"); + writeIntersection(position, candidate.surface()); - currentVolume = - candidate.portal->resolveVolume(gctx, position, direction).value(); + if (candidate.portal != nullptr) { + ACTS_VERBOSE( + "On portal: " << candidate.portal->surface().toStream(gctx)); + currentVolume = + candidate.portal->resolveVolume(gctx, position, direction).value(); - if (currentVolume == nullptr) { - ACTS_VERBOSE("switched to nullptr"); + if (currentVolume == nullptr) { + ACTS_VERBOSE("switched to nullptr -> we're done"); + terminated = true; + } + break; + + } else { + ACTS_VERBOSE("Not on portal"); + } + + main.switchToNextCandidate(); + } + + if (terminated) { + ACTS_VERBOSE("Terminate pseudo navigation"); break; } @@ -335,11 +395,11 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { }; ec.addLayer("PixelNeg1", [&](auto& layer) { - makeLayer(base * Translation3{Vector3{0, 0, -600_mm}}, layer); + makeLayer(base * Translation3{Vector3{0, 0, -700_mm}}, layer); }); ec.addLayer("PixelNeg2", [&](auto& layer) { - makeLayer(base * Translation3{Vector3{0, 0, -400_mm}}, layer); + makeLayer(base * Translation3{Vector3{0, 0, -500_mm}}, layer); }); }); @@ -347,28 +407,35 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { "PixelBarrel", BinningValue::binR, [&](auto& brl) { brl.setAttachmentStrategy( CylinderVolumeStack::AttachmentStrategy::Gap) - .setResizeStrategy( - CylinderVolumeStack::ResizeStrategy::Expand); - - brl.addStaticVolume( - base, - std::make_shared(23_mm, 48_mm, 200_mm), - "PixelLayer0"); + .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); + + auto makeLayer = [&](const std::string& name, double r, + std::size_t nStaves, int nSensorsPerStave) { + brl.addLayer(name, [&](auto& layer) { + std::vector> surfaces = + makeBarrelLayer(base, detectorElements, r, nStaves, + nSensorsPerStave, 2.5_mm, 10_mm, 20_mm); + + layer.setSurfaces(surfaces) + .setLayerType(LayerBlueprintNode::LayerType::Cylinder) + .setEnvelope(ExtentEnvelope{{ + .z = {5_mm, 5_mm}, + .r = {1_mm, 1_mm}, + }}) + .setTransform(base); + }); + }; - brl.addStaticVolume( - base, - std::make_shared(87_mm, 103_mm, 250_mm), - "PixelLayer1"); + makeLayer("PixelLayer0", 30_mm, 18, 5); + makeLayer("PixelLayer1", 90_mm, 30, 6); brl.addStaticVolume(base, std::make_shared( - 150_mm, 180_mm, 310_mm), - "PixelLayer2"); + 100_mm, 110_mm, 250_mm), + "PixelSupport"); - brl.addStaticVolume(base, - std::make_shared( - 250_mm, 400_mm, 310_mm), - "PixelLayer3"); + makeLayer("PixelLayer2", 150_mm, 40, 7); + makeLayer("PixelLayer3", 250_mm, 70, 8); }); auto& ec = @@ -405,20 +472,20 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { Vector3 position = Vector3::Zero(); std::ofstream csv{"api_test_container.csv"}; - csv << "x,y,z,volume,boundary" << std::endl; + csv << "x,y,z,volume,boundary,sensitive" << std::endl; std::mt19937 rnd{42}; std::uniform_real_distribution<> dist{-1, 1}; - double etaWidth = 5.0; + double etaWidth = 3; double thetaMin = 2 * std::atan(std::exp(-etaWidth)); double thetaMax = 2 * std::atan(std::exp(etaWidth)); std::uniform_real_distribution<> thetaDist{thetaMin, thetaMax}; using namespace Acts::UnitLiterals; - for (std::size_t i = 0; i < 5; i++) { + for (std::size_t i = 0; i < 5000; i++) { double theta = thetaDist(rnd); double phi = 2 * M_PI * dist(rnd); @@ -428,7 +495,7 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { direction[2] = std::cos(theta); pseudoNavigation(*trackingGeometry, position, direction, csv, i, 2, - *logger->clone(std::nullopt, Logging::VERBOSE)); + *logger->clone(std::nullopt, Logging::DEBUG)); // portalSamples(*trackingGeometry, position, direction, csv, i); } @@ -504,7 +571,7 @@ BOOST_AUTO_TEST_CASE(NodeApiTestConfined) { BOOST_CHECK_EQUAL(wrapper->volumes().size(), 4); } -BOOST_AUTO_TEST_CASE(LayerNode) { +BOOST_AUTO_TEST_CASE(LayerNodeDisk) { double yrot = 45_degree; Transform3 base = Transform3::Identity() * AngleAxis3{yrot, Vector3::UnitY()}; @@ -512,7 +579,7 @@ BOOST_AUTO_TEST_CASE(LayerNode) { auto makeFan = [&](double thickness) { detectorElements.clear(); - return makeFanLayer(base, detectorElements, thickness); + return makeFanLayer(base, detectorElements, 200_mm, 10, thickness); }; std::vector> surfaces = makeFan(2.5_mm); @@ -532,7 +599,54 @@ BOOST_AUTO_TEST_CASE(LayerNode) { .setTransform(base); }); - std::ofstream dot{"layer_node.dot"}; + std::ofstream dot{"layer_node_disk.dot"}; + root.graphViz(dot); + + auto trackingGeometry = + root.construct({}, gctx, *logger->clone(std::nullopt, Logging::VERBOSE)); + + ObjVisualization3D vis; + + trackingGeometry->visualize(vis, gctx, {}, {}); + + vis.write("layer_node_disk.obj"); + + std::size_t nSurfaces = 0; + + trackingGeometry->visitSurfaces([&](const Surface* surface) { + if (surface->associatedDetectorElement() != nullptr) { + nSurfaces++; + } + }); + + BOOST_CHECK_EQUAL(nSurfaces, surfaces.size()); +} + +BOOST_AUTO_TEST_CASE(LayerNodeCylinder) { + double yrot = 0_degree; + Transform3 base = Transform3::Identity() * AngleAxis3{yrot, Vector3::UnitY()}; + + std::vector> detectorElements; + + std::vector> surfaces = + makeBarrelLayer(base, detectorElements, 300_mm, 24, 8, 2.5_mm); + + RootBlueprintNode root{{.envelope{{ + .z = {2_mm, 2_mm}, + .r = {3_mm, 5_mm}, + }}}}; + + root.addLayer("Layer0", [&](auto& layer) { + layer.setSurfaces(surfaces) + .setLayerType(LayerBlueprintNode::LayerType::Cylinder) + .setEnvelope(ExtentEnvelope{{ + .z = {10_mm, 10_mm}, + .r = {20_mm, 10_mm}, + }}) + .setTransform(base); + }); + + std::ofstream dot{"layer_node_cyl.dot"}; root.graphViz(dot); auto trackingGeometry = @@ -542,7 +656,7 @@ BOOST_AUTO_TEST_CASE(LayerNode) { trackingGeometry->visualize(vis, gctx, {}, {}); - vis.write("layer_node.obj"); + vis.write("layer_node_cyl.obj"); std::size_t nSurfaces = 0; From 91d12dbf507101c494a21c976f9da1231ce64018 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 2 Oct 2024 09:26:52 +0200 Subject: [PATCH 035/100] blueprint: TODO item --- Core/src/Geometry/RootBlueprintNode.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index 92753610024..aa99fad2d96 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -131,6 +131,7 @@ std::unique_ptr RootBlueprintNode::construct( child.finalize(options, *world, logger); // @TODO: Handle material decorator, geo id hook + // @TODO: Maybe add a name uniqueness check return std::make_unique( std::move(world), nullptr, m_cfg.geometryIdentifierHook, logger); From eca18676d6b5fcb95091301db1d8836778ed3cff Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 2 Oct 2024 09:27:02 +0200 Subject: [PATCH 036/100] blueprint: Add TryAllSurfaces as default policy --- Core/src/Geometry/BlueprintNode.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index 37a14b8d94d..9d7894d4ba5 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -59,6 +59,7 @@ std::unique_ptr BlueprintNode::Options::makeDefaultNavigationPolicyFactory() { return NavigationPolicyFactory::make() .add() + .add() .asUniquePtr(); } From 30b5d626ce336a7b447faf1f1df7985d04d2de25 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 2 Oct 2024 15:43:16 +0200 Subject: [PATCH 037/100] blueprint: Remove Blueprint.cpp --- Core/src/Geometry/Blueprint.cpp | 15 --------------- Core/src/Geometry/CMakeLists.txt | 1 - 2 files changed, 16 deletions(-) delete mode 100644 Core/src/Geometry/Blueprint.cpp diff --git a/Core/src/Geometry/Blueprint.cpp b/Core/src/Geometry/Blueprint.cpp deleted file mode 100644 index 5cb6a54efd0..00000000000 --- a/Core/src/Geometry/Blueprint.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// This file is part of the ACTS project. -// -// Copyright (C) 2016 CERN for the benefit of the ACTS project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "Acts/Geometry/Blueprint.hpp" - -namespace Acts { - -std::unique_ptr Blueprint::build() {} - -} // namespace Acts diff --git a/Core/src/Geometry/CMakeLists.txt b/Core/src/Geometry/CMakeLists.txt index 5c0454ceac2..06a71b8cbc6 100644 --- a/Core/src/Geometry/CMakeLists.txt +++ b/Core/src/Geometry/CMakeLists.txt @@ -48,5 +48,4 @@ target_sources( CylinderContainerBlueprintNode.cpp StaticBlueprintNode.cpp LayerBlueprintNode.cpp - Blueprint.cpp ) From c81ecdb720e7ff133145a395a7742072a762b799 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 2 Oct 2024 15:46:11 +0200 Subject: [PATCH 038/100] blueprint: python script works again --- Examples/Python/src/Blueprint.cpp | 54 ++++++++++++++++++++-------- Examples/Scripts/Python/blueprint.py | 16 +++++---- 2 files changed, 49 insertions(+), 21 deletions(-) diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index dad23a29c8a..8f31744a9eb 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -10,6 +10,7 @@ #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/CylinderVolumeStack.hpp" #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" +#include "Acts/Geometry/RootBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Plugins/Python/Utilities.hpp" #include "Acts/Utilities/BinningType.hpp" @@ -188,21 +189,16 @@ void addBlueprint(Context& ctx) { .def_property_readonly("children", py::overload_cast<>(&BlueprintNode::children)) .def_property_readonly("name", &BlueprintNode::name) - .def("graphViz", - [](BlueprintNode& self, const py::object& fh) { - std::stringstream ss; - self.graphViz(ss); - fh.attr("write")(ss.str()); - }) - .def( - "build", - [](BlueprintNode& self, const GeometryContext& gctx, - Logging::Level level) { - // @TODO: Make options configurable - return self.build({}, gctx, - *getDefaultLogger("Blueprint", level)); - }, - py::arg("gctx"), py::arg("level") = Logging::INFO); + .def("graphViz", [](BlueprintNode& self, const py::object& fh) { + std::stringstream ss; + self.graphViz(ss); + fh.attr("write")(ss.str()); + }); + + // @TODO: Add ability to provide policy factories + // This needs a way to produce them in python! + py::class_(blueprintNode, "Options") + .def(py::init<>()); py::class_(blueprintNode, "MutableChildRange") @@ -226,6 +222,34 @@ void addBlueprint(Context& ctx) { return self.size(); }); + { + auto n = + py::class_>(m, "RootBlueprintNode"); + + n.def(py::init()) + .def_property_readonly("name", &RootBlueprintNode::name) + // Return value needs to be shared pointer because python otherwise + // can't manage the lifetime + .def( + "construct", + [](RootBlueprintNode& self, + const RootBlueprintNode::Options& options, + const GeometryContext& gctx, + Logging::Level level) -> std::shared_ptr { + return self.construct( + options, gctx, *getDefaultLogger("RootBlueprintNode", level)); + }, + py::arg("options"), py::arg("gctx"), + py::arg("level") = Logging::INFO); + + auto c = py::class_(n, "Config").def(py::init()); + ACTS_PYTHON_STRUCT_BEGIN(c, RootBlueprintNode::Config); + ACTS_PYTHON_MEMBER(envelope); + ACTS_PYTHON_MEMBER(geometryIdentifierHook); + ACTS_PYTHON_STRUCT_END(); + } + py::class_>(m, "StaticBlueprintNode") diff --git a/Examples/Scripts/Python/blueprint.py b/Examples/Scripts/Python/blueprint.py index 0365edeb848..079e40c3226 100755 --- a/Examples/Scripts/Python/blueprint.py +++ b/Examples/Scripts/Python/blueprint.py @@ -7,7 +7,8 @@ mm = acts.UnitConstants.mm degree = acts.UnitConstants.degree -root = acts.CylinderContainerBlueprintNode("root", acts.BinningValue.binR) +root = acts.RootBlueprintNode(envelope=acts.ExtentEnvelope(r=[10 * mm, 10 * mm])) + pixel = root.addCylinderContainer(direction=acts.BinningValue.binZ, name="Pixel") print(repr(pixel)) @@ -85,11 +86,14 @@ def PixelEndcapDisk(disk): with open("blueprint.dot", "w") as fh: root.graphViz(fh) -vis = acts.ObjVisualization3D() - -volume = root.build(level=acts.logging.VERBOSE) gctx = acts.GeometryContext() -root.visualize(vis, gctx) +trackingGeometry = root.construct( + options=acts.BlueprintNode.Options(), gctx=gctx, level=acts.logging.VERBOSE +) -vis.write(Path("blueprint.obj")) +vis = acts.ObjVisualization3D() +trackingGeometry.visualize(vis, gctx) +with Path("blueprint.obj").open("w") as fh: + vis.write(fh) +# print("DONE") From ca4bf9b165cf5236f3315d95b3fa1aa267b94671 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 4 Oct 2024 15:18:15 +0200 Subject: [PATCH 039/100] blueprint: api evolution --- .../Acts/Geometry/LayerBlueprintNode.hpp | 8 + .../CylinderContainerBlueprintNode.cpp | 3 +- Core/src/Geometry/LayerBlueprintNode.cpp | 17 + Examples/Python/src/Blueprint.cpp | 487 +++++++++++------- Examples/Python/src/Geometry.cpp | 10 + Examples/Scripts/Python/blueprint.py | 12 +- 6 files changed, 345 insertions(+), 192 deletions(-) diff --git a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp index 4cbe60762c4..9ea5298b0ba 100644 --- a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp @@ -32,12 +32,20 @@ class LayerBlueprintNode : public StaticBlueprintNode { LayerBlueprintNode& setSurfaces( std::vector> surfaces); + const std::vector>& surfaces() const; + LayerBlueprintNode& setTransform(const Transform3& transform); + const Transform3& transform() const; + LayerBlueprintNode& setEnvelope(const ExtentEnvelope& envelope); + const ExtentEnvelope& envelope() const; + LayerBlueprintNode& setLayerType(LayerType layerType); + const LayerType& layerType() const; + void addToGraphviz(std::ostream& os) const override; private: diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 4872465012e..533f9a2b2c6 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -38,7 +38,8 @@ const std::string& CylinderContainerBlueprintNode::name() const { Volume& CylinderContainerBlueprintNode::build(const Options& options, const GeometryContext& gctx, const Logger& logger) { - ACTS_DEBUG(prefix() << "cylinder container build"); + ACTS_DEBUG(prefix() << "cylinder container build (dir=" << m_direction + << ")"); if (m_stack != nullptr) { ACTS_ERROR(prefix() << "Volume is already built"); diff --git a/Core/src/Geometry/LayerBlueprintNode.cpp b/Core/src/Geometry/LayerBlueprintNode.cpp index 1b674396d77..9eb1af43035 100644 --- a/Core/src/Geometry/LayerBlueprintNode.cpp +++ b/Core/src/Geometry/LayerBlueprintNode.cpp @@ -104,23 +104,40 @@ LayerBlueprintNode& LayerBlueprintNode::setSurfaces( return *this; } +const std::vector>& LayerBlueprintNode::surfaces() + const { + return m_surfaces; +} + LayerBlueprintNode& LayerBlueprintNode::setTransform( const Transform3& transform) { m_transform = transform; return *this; } +const Transform3& LayerBlueprintNode::transform() const { + return m_transform; +} + LayerBlueprintNode& LayerBlueprintNode::setEnvelope( const ExtentEnvelope& envelope) { m_envelope = envelope; return *this; } +const ExtentEnvelope& LayerBlueprintNode::envelope() const { + return m_envelope; +} + LayerBlueprintNode& LayerBlueprintNode::setLayerType(LayerType layerType) { m_layerType = layerType; return *this; } +const LayerBlueprintNode::LayerType& LayerBlueprintNode::layerType() const { + return m_layerType; +} + void LayerBlueprintNode::addToGraphviz(std::ostream& os) const { std::stringstream ss; ss << "" << name() << ""; diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 8f31744a9eb..830f551211b 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -6,194 +6,249 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. +#include "Acts/Definitions/Units.hpp" #include "Acts/Geometry/BlueprintNode.hpp" #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/CylinderVolumeStack.hpp" +#include "Acts/Geometry/LayerBlueprintNode.hpp" #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/RootBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" +#include "Acts/Navigation/NavigationStream.hpp" #include "Acts/Plugins/Python/Utilities.hpp" #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Logger.hpp" +#include +#include #include #include #include #include +#include namespace py = pybind11; using namespace pybind11::literals; namespace Acts::Python { -void addBlueprint(Context& ctx) { - auto m = ctx.get("main"); +namespace { +using std::uniform_real_distribution; - struct AddCylinderContainerHelper { - BlueprintNode& parent; - BinningValue direction; - std::optional name; - - std::shared_ptr operator()( - const py::function& callback) { - auto cylinder = std::make_shared( - name.value_or(callback.attr("__name__").cast()), - direction); - parent.addChild(cylinder); - callback(cylinder); - return cylinder; - } +// This is temporary! +void pseudoNavigation(const TrackingGeometry& trackingGeometry, + const GeometryContext& gctx, std::filesystem::path& path, + std::size_t runs, std::size_t substepsPerCm, + Logging::Level logLevel) { + using namespace Acts::UnitLiterals; - std::shared_ptr enter() { - if (!name.has_value()) { - throw std::invalid_argument("Name is required in context manager"); - } - auto cylinder = std::make_shared( - name.value(), direction); - parent.addChild(cylinder); - return cylinder; - } + ACTS_LOCAL_LOGGER(getDefaultLogger("pseudoNavigation", logLevel)); - void exit(const py::object& /*unused*/, const py::object& /*unused*/, - const py::object& /*unused*/) {} - }; + std::ofstream csv{path}; + csv << "x,y,z,volume,boundary,sensitive" << std::endl; - py::class_(m, "_AddCylinderContainerHelper") - .def("__call__", &AddCylinderContainerHelper::operator()) - .def("__enter__", &AddCylinderContainerHelper::enter) - .def("__exit__", &AddCylinderContainerHelper::exit); + std::mt19937 rnd{42}; - struct AddMaterialDesignatorHelper { - BlueprintNode& parent; + std::uniform_real_distribution<> dist{-1, 1}; + std::uniform_real_distribution<> subStepDist{0.01, 0.99}; - std::shared_ptr operator()(const py::function& callback) { - auto material = std::make_shared(); - parent.addChild(material); - callback(material); - return material; - } + double etaWidth = 4.5; + double thetaMin = 2 * std::atan(std::exp(-etaWidth)); + double thetaMax = 2 * std::atan(std::exp(etaWidth)); + std::uniform_real_distribution<> thetaDist{thetaMin, thetaMax}; - std::shared_ptr enter() { - auto material = std::make_shared(); - parent.addChild(material); - return material; - } + using namespace Acts::UnitLiterals; - void exit(const py::object& /*unused*/, const py::object& /*unused*/, - const py::object& /*unused*/) {} - }; + for (std::size_t run = 0; run < runs; run++) { + Vector3 position = Vector3::Zero(); - py::class_(m, "_AddMaterialDesignatorHelper") - .def("__call__", &AddMaterialDesignatorHelper::operator()) - .def("__enter__", &AddMaterialDesignatorHelper::enter) - .def("__exit__", &AddMaterialDesignatorHelper::exit); - - struct AddStaticVolumeHelper { - BlueprintNode& parent; - Transform3 transform; - std::shared_ptr bounds; - std::optional name; - - std::shared_ptr operator()( - const py::function& callback) { - std::string callbackName = callback.attr("__name__").cast(); - auto node = std::make_shared( - std::make_unique(transform, bounds, - name.value_or(callbackName))); - parent.addChild(node); - callback(node); - return node; - } + double theta = thetaDist(rnd); + double phi = 2 * M_PI * dist(rnd); + + Vector3 direction; + direction[0] = std::sin(theta) * std::cos(phi); + direction[1] = std::sin(theta) * std::sin(phi); + direction[2] = std::cos(theta); - std::shared_ptr enter() { - if (!name.has_value()) { - throw std::invalid_argument("Name is required in context manager"); + ACTS_VERBOSE("start navigation " << run); + ACTS_VERBOSE("pos: " << position.transpose()); + ACTS_VERBOSE("dir: " << direction.transpose()); + ACTS_VERBOSE(direction.norm()); + + std::mt19937 rng{static_cast(run)}; + + const auto* volume = trackingGeometry.lowestTrackingVolume(gctx, position); + assert(volume != nullptr); + ACTS_VERBOSE(volume->volumeName()); + + NavigationStream main; + const TrackingVolume* currentVolume = volume; + + csv << run << "," << position[0] << "," << position[1] << "," + << position[2]; + csv << "," << volume->geometryId().volume(); + csv << "," << volume->geometryId().boundary(); + csv << "," << volume->geometryId().sensitive(); + csv << std::endl; + + ACTS_VERBOSE("start pseudo navigation"); + + for (std::size_t i = 0; i < 100; i++) { + assert(currentVolume != nullptr); + main = NavigationStream{}; + + currentVolume->updateNavigationState( + {.main = main, .position = position, .direction = direction}); + + ACTS_VERBOSE(main.candidates().size() << " candidates"); + + for (const auto& candidate : main.candidates()) { + ACTS_VERBOSE(" -> " << candidate.surface().geometryId()); + ACTS_VERBOSE(" " << candidate.surface().toStream(gctx)); } - auto node = std::make_shared( - std::make_unique(transform, bounds, - name.value())); - parent.addChild(node); - return node; + + ACTS_VERBOSE("initializing candidates"); + main.initialize(gctx, {position, direction}, BoundaryTolerance::None()); + + ACTS_VERBOSE(main.candidates().size() << " candidates remaining"); + + for (const auto& candidate : main.candidates()) { + ACTS_VERBOSE(" -> " << candidate.surface().geometryId()); + ACTS_VERBOSE(" " << candidate.surface().toStream(gctx)); + } + + if (main.currentCandidate().surface().isOnSurface(gctx, position, + direction)) { + ACTS_VERBOSE( + "Already on surface at initialization, skipping candidate"); + + auto id = main.currentCandidate().surface().geometryId(); + csv << run << "," << position[0] << "," << position[1] << "," + << position[2]; + csv << "," << id.volume(); + csv << "," << id.boundary(); + csv << "," << id.sensitive(); + csv << std::endl; + if (!main.switchToNextCandidate()) { + ACTS_WARNING("candidates exhausted unexpectedly"); + break; + } + } + + auto writeIntersection = [&](const Vector3& position, + const Surface& surface) { + csv << run << "," << position[0] << "," << position[1] << "," + << position[2]; + csv << "," << surface.geometryId().volume(); + csv << "," << surface.geometryId().boundary(); + csv << "," << surface.geometryId().sensitive(); + csv << std::endl; + }; + + bool terminated = false; + while (main.remainingCandidates() > 0) { + const auto& candidate = main.currentCandidate(); + + ACTS_VERBOSE(candidate.portal); + ACTS_VERBOSE(candidate.intersection.position().transpose()); + + ACTS_VERBOSE("moving to position: " << position.transpose() << " (r=" + << VectorHelpers::perp(position) + << ")"); + + Vector3 delta = candidate.intersection.position() - position; + + std::size_t substeps = + std::max(1l, std::lround(delta.norm() / 10_cm * substepsPerCm)); + + for (std::size_t j = 0; j < substeps; j++) { + // position += delta / (substeps + 1); + Vector3 subpos = position + subStepDist(rng) * delta; + csv << run << "," << subpos[0] << "," << subpos[1] << "," + << subpos[2]; + csv << "," << currentVolume->geometryId().volume(); + csv << ",0,0"; // zero boundary and sensitive ids + csv << std::endl; + } + + position = candidate.intersection.position(); + ACTS_VERBOSE(" -> " + << position.transpose() + << " (r=" << VectorHelpers::perp(position) << ")"); + + writeIntersection(position, candidate.surface()); + + if (candidate.portal != nullptr) { + ACTS_VERBOSE( + "On portal: " << candidate.portal->surface().toStream(gctx)); + currentVolume = + candidate.portal->resolveVolume(gctx, position, direction) + .value(); + + if (currentVolume == nullptr) { + ACTS_VERBOSE("switched to nullptr -> we're done"); + terminated = true; + } + break; + + } else { + ACTS_VERBOSE("Not on portal"); + } + + main.switchToNextCandidate(); + } + + if (terminated) { + ACTS_VERBOSE("Terminate pseudo navigation"); + break; + } + + ACTS_VERBOSE("switched to " << currentVolume->volumeName()); + + ACTS_VERBOSE("-----"); } + } +} - void exit(const py::object& /*type*/, const py::object& /*value*/, - const py::object& /*traceback*/) {} - }; +} // namespace - py::class_(m, "_AddStaticVolumeHelper") - .def("__call__", &AddStaticVolumeHelper::operator()) - .def("__enter__", &AddStaticVolumeHelper::enter) - .def("__exit__", &AddStaticVolumeHelper::exit); +void addBlueprint(Context& ctx) { + auto m = ctx.get("main"); auto blueprintNode = - py::class_>(m, - "BlueprintNode") - .def("__str__", - [](const BlueprintNode& self) { - std::stringstream ss; - self.toStream(ss); - return ss.str(); - }) - .def( - "addStaticVolume", - [](BlueprintNode& self, const Transform3& transform, - const std::shared_ptr& bounds, - const std::string& name) { - auto node = std::make_shared( - std::make_unique(transform, bounds, - name)); - self.addChild(node); - return node; - }, - py::arg("transform"), py::arg("bounds"), - py::arg("name") = "undefined") - - .def( - "StaticVolume", - [](BlueprintNode& self, const Transform3& transform, - std::shared_ptr bounds, - const std::optional& name = std::nullopt) { - return AddStaticVolumeHelper{self, transform, std::move(bounds), - name.value_or("undefined")}; - }, - py::arg("transform"), py::arg("bounds"), - py::arg("name") = std::nullopt) - - .def( - "addCylinderContainer", - [](BlueprintNode& self, const std::string& name, - BinningValue direction) { - auto cylinder = - std::make_shared(name, - direction); - self.addChild(cylinder); - return cylinder; - }, - py::arg("name"), py::arg("direction")) - - .def( - "CylinderContainer", - [](BlueprintNode& self, BinningValue direction, - std::optional name = std::nullopt) { - return AddCylinderContainerHelper{self, direction, - std::move(name)}; - }, - py::arg("direction"), py::arg("name") = std::nullopt) - - .def("Material", - [](BlueprintNode& self) { - return AddMaterialDesignatorHelper{self}; - }) - - .def("addChild", &BlueprintNode::addChild) - .def_property_readonly("children", - py::overload_cast<>(&BlueprintNode::children)) - .def_property_readonly("name", &BlueprintNode::name) - .def("graphViz", [](BlueprintNode& self, const py::object& fh) { - std::stringstream ss; - self.graphViz(ss); - fh.attr("write")(ss.str()); - }); + py::class_>( + m, "BlueprintNode"); + + auto addContextManagerProtocol = [](class_& cls) { + using type = class_::type; + cls.def("__enter__", [](type& self) -> type& { return self; }) + .def("__exit__", [](type& /*self*/, const py::object& /*exc_type*/, + const py::object& /*exc_value*/, + const py::object& /*traceback*/) {}); + }; + + auto addNodeMethods = [&blueprintNode](const std::string& name, + auto&& callable, auto&&... args) { + blueprintNode.def(name.c_str(), callable, args...) + .def(("add" + name).c_str(), callable, args...); + }; + + blueprintNode + .def("__str__", + [](const BlueprintNode& self) { + std::stringstream ss; + self.toStream(ss); + return ss.str(); + }) + .def("addChild", &BlueprintNode::addChild) + .def_property_readonly("children", + py::overload_cast<>(&BlueprintNode::children)) + .def_property_readonly("name", &BlueprintNode::name) + .def("graphViz", [](BlueprintNode& self, const py::object& fh) { + std::stringstream ss; + self.graphViz(ss); + fh.attr("write")(ss.str()); + }); // @TODO: Add ability to provide policy factories // This needs a way to produce them in python! @@ -250,18 +305,32 @@ void addBlueprint(Context& ctx) { ACTS_PYTHON_STRUCT_END(); } - py::class_>(m, - "StaticBlueprintNode") - .def(py::init([](const Transform3& transform, - const std::shared_ptr& bounds, - const std::string& name) { - return std::make_shared( - std::make_unique(transform, bounds, - name)); - }), - py::arg("transform"), py::arg("bounds"), - py::arg("name") = "undefined"); + auto staticNode = + py::class_>( + m, "StaticBlueprintNode") + .def(py::init([](const Transform3& transform, + const std::shared_ptr& bounds, + const std::string& name) { + return std::make_shared( + std::make_unique(transform, bounds, + name)); + }), + py::arg("transform"), py::arg("bounds"), + py::arg("name") = "undefined"); + + addContextManagerProtocol(staticNode); + + addNodeMethods( + "StaticVolume", + [](BlueprintNode& self, const Transform3& transform, + const std::shared_ptr& bounds, const std::string& name) { + auto node = std::make_shared( + std::make_unique(transform, bounds, name)); + self.addChild(node); + return node; + }, + py::arg("transform"), py::arg("bounds"), py::arg("name") = "undefined"); auto cylNode = py::class_(name, direction); + self.addChild(cylinder); + return cylinder; + }, + py::arg("name"), py::arg("direction")); + + auto matNode = + py::class_>( + m, "MaterialDesignatorBlueprintNode") + .def(py::init<>()); + + addContextManagerProtocol(matNode); + + addNodeMethods("Material", [](BlueprintNode& self) { + auto child = std::make_shared(); + self.addChild(child); + return child; + }); + + auto layerNode = + py::class_>( + m, "LayerBlueprintNode") + .def(py::init(), py::arg("name")) + .def_property_readonly("name", &Acts::LayerBlueprintNode::name) + .def_property("surfaces", &Acts::LayerBlueprintNode::surfaces, + &Acts::LayerBlueprintNode::setSurfaces) + .def_property("transform", &Acts::LayerBlueprintNode::transform, + &Acts::LayerBlueprintNode::setTransform) + .def_property("envelope", &Acts::LayerBlueprintNode::envelope, + &Acts::LayerBlueprintNode::setEnvelope) + .def_property("layerType", &Acts::LayerBlueprintNode::layerType, + &Acts::LayerBlueprintNode::setLayerType); + + py::enum_(layerNode, "LayerType") + .value("Cylinder", Acts::LayerBlueprintNode::LayerType::Cylinder) + .value("Disc", Acts::LayerBlueprintNode::LayerType::Disc) + .value("Plane", Acts::LayerBlueprintNode::LayerType::Plane); + + addContextManagerProtocol(layerNode); + + addNodeMethods( + "Layer", + [](BlueprintNode& self, const std::string& name) { + auto child = std::make_shared(name); + self.addChild(child); + return child; + }, + py::arg("name")); + + // TEMPORARY + m.def("pseudoNavigation", &pseudoNavigation, "trackingGeometry"_a, "gctx"_a, + "path"_a, "runs"_a, "substepsPerCm"_a = 2, + "logLevel"_a = Logging::INFO); } } // namespace Acts::Python diff --git a/Examples/Python/src/Geometry.cpp b/Examples/Python/src/Geometry.cpp index 2d5ef4e8994..e9bbbfa350e 100644 --- a/Examples/Python/src/Geometry.cpp +++ b/Examples/Python/src/Geometry.cpp @@ -30,6 +30,7 @@ #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/GeometryHierarchyMap.hpp" #include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Geometry/ProtoLayer.hpp" #include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Geometry/Volume.hpp" #include "Acts/Geometry/VolumeBounds.hpp" @@ -707,6 +708,15 @@ void addExperimentalGeometry(Context& ctx) { ACTS_PYTHON_DECLARE_ALGORITHM(ActsExamples::VolumeAssociationTest, mex, "VolumeAssociationTest", name, ntests, randomNumbers, randomRange, detector); + + py::class_(m, "ProtoLayer") + .def(py::init>&, + const Transform3&>(), + "gctx"_a, "surfaces"_a, "transform"_a = Transform3::Identity()) + .def("min", &ProtoLayer::min, "bval"_a, "addenv"_a = true) + .def("max", &ProtoLayer::max, "bval"_a, "addenv"_a = true) + .def_property_readonly("surfaces", &ProtoLayer::surfaces); } } // namespace Acts::Python diff --git a/Examples/Scripts/Python/blueprint.py b/Examples/Scripts/Python/blueprint.py index 079e40c3226..6f4eb829bb9 100755 --- a/Examples/Scripts/Python/blueprint.py +++ b/Examples/Scripts/Python/blueprint.py @@ -37,8 +37,7 @@ if True: - @pixel.CylinderContainer(acts.BinningValue.binZ) - def PixelPosEndcap(ec): + with pixel.CylinderContainer("PixelPosEndcap", acts.BinningValue.binZ) as ec: print("Positive Endcap") ec.attachmentStrategy = acts.CylinderVolumeStack.AttachmentStrategy.Gap @@ -52,16 +51,17 @@ def PixelPosEndcap(ec): trf = acts.Transform3.Identity() * acts.Translation3(acts.Vector3(0, 0, z)) - @ec.StaticVolume(trf, bounds, name=f"PixelPosEndcapDisk{i}") - def PixelEndcapDisk(disk): + with ec.StaticVolume(trf, bounds, name=f"PixelPosEndcapDisk{i}") as disc: print("Add disk", i) - assert PixelEndcapDisk.name == f"PixelPosEndcapDisk{i}" + assert disc.name == f"PixelPosEndcapDisk{i}" if True: with pixel.Material() as mat: - with mat.CylinderContainer(acts.BinningValue.binZ, name="PixelNegEndcap") as ec: + with mat.CylinderContainer( + direction=acts.BinningValue.binZ, name="PixelNegEndcap" + ) as ec: ec.attachmentStrategy = acts.CylinderVolumeStack.AttachmentStrategy.Gap print("Negative Endcap") From af660148122d860e2caa9eabf2fee18c2ce89792 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 6 Nov 2024 15:26:13 +0100 Subject: [PATCH 040/100] blueprint: ray test configuration --- Examples/Python/src/Blueprint.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 830f551211b..903f4c15897 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -39,6 +39,7 @@ using std::uniform_real_distribution; void pseudoNavigation(const TrackingGeometry& trackingGeometry, const GeometryContext& gctx, std::filesystem::path& path, std::size_t runs, std::size_t substepsPerCm, + std::pair etaRange, Logging::Level logLevel) { using namespace Acts::UnitLiterals; @@ -52,9 +53,8 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, std::uniform_real_distribution<> dist{-1, 1}; std::uniform_real_distribution<> subStepDist{0.01, 0.99}; - double etaWidth = 4.5; - double thetaMin = 2 * std::atan(std::exp(-etaWidth)); - double thetaMax = 2 * std::atan(std::exp(etaWidth)); + double thetaMin = 2 * std::atan(std::exp(-etaRange.first)); + double thetaMax = 2 * std::atan(std::exp(-etaRange.second)); std::uniform_real_distribution<> thetaDist{thetaMin, thetaMax}; using namespace Acts::UnitLiterals; @@ -372,15 +372,21 @@ void addBlueprint(Context& ctx) { py::class_>( m, "MaterialDesignatorBlueprintNode") - .def(py::init<>()); + .def(py::init(), + "name"_a, "binning"_a); addContextManagerProtocol(matNode); - addNodeMethods("Material", [](BlueprintNode& self) { - auto child = std::make_shared(); - self.addChild(child); - return child; - }); + addNodeMethods( + "Material", + [](BlueprintNode& self, const std::string& name, + const Experimental::ProtoBinning& binning) { + auto child = + std::make_shared(name, binning); + self.addChild(child); + return child; + }, + "name"_a, "binning"_a); auto layerNode = py::class_ Date: Wed, 9 Oct 2024 10:51:01 +0200 Subject: [PATCH 041/100] blueprint: material designator --- Core/include/Acts/Geometry/BlueprintNode.hpp | 1 + .../MaterialDesignatorBlueprintNode.hpp | 68 ++++----- Core/src/Geometry/BlueprintNode.cpp | 3 +- Core/src/Geometry/CMakeLists.txt | 1 + .../MaterialDesignatorBlueprintNode.cpp | 143 ++++++++++++++++++ Examples/Python/src/Blueprint.cpp | 66 ++++---- 6 files changed, 219 insertions(+), 63 deletions(-) create mode 100644 Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index e42e2e4b95e..2630b2729c3 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -77,6 +77,7 @@ class BlueprintNode { callback = {}); MaterialDesignatorBlueprintNode& addMaterial( + const std::string& name, const std::function& callback = {}); diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index fed6cff4d7b..532b8428a1b 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -8,59 +8,59 @@ #pragma once +#include "Acts/Detector/ProtoBinning.hpp" #include "Acts/Geometry/BlueprintNode.hpp" -#include "Acts/Surfaces/Surface.hpp" -#include "Acts/Utilities/GraphViz.hpp" +#include "Acts/Geometry/PortalShell.hpp" + +#include +#include namespace Acts { class MaterialDesignatorBlueprintNode final : public BlueprintNode { public: - const std::string& name() const override { - const static std::string s_name = "Material"; - return s_name; - } + // @TODO: This needs cuboid volume storage as well + // @TODO: I don't love the type + using BinningConfig = std::variant>>; - void toStream(std::ostream& os) const override { - os << "MaterialDesignatorBlueprintNode(" << name() << ")"; - } + MaterialDesignatorBlueprintNode(const std::string& name) : m_name(name) {} + + const std::string& name() const override; + + void toStream(std::ostream& os) const override; Volume& build(const Options& options, const GeometryContext& gctx, - const Logger& logger = Acts::getDummyLogger()) override { - if (children().size() != 1) { - throw std::runtime_error( - "MaterialDesignatorBlueprintNode must have exactly one child"); - } - return children().at(0).build(options, gctx, logger); - } + const Logger& logger = Acts::getDummyLogger()) override; PortalShellBase& connect( const Options& options, const GeometryContext& gctx, - const Logger& logger = Acts::getDummyLogger()) override { - if (children().size() != 1) { - throw std::runtime_error( - "MaterialDesignatorBlueprintNode must have exactly one child"); - } - return children().at(0).connect(options, gctx, logger); - } + const Logger& logger = Acts::getDummyLogger()) override; void finalize(const Options& options, TrackingVolume& parent, - const Logger& logger) override { - if (children().size() != 1) { - throw std::runtime_error( - "MaterialDesignatorBlueprintNode must have exactly one child"); - } - return children().at(0).finalize(options, parent, logger); + const Logger& logger) override; + + void addToGraphviz(std::ostream& os) const override; + + const std::optional& binning() { return m_binning; } + + MaterialDesignatorBlueprintNode& setBinning(BinningConfig binning) { + m_binning = std::move(binning); + return *this; } - void addToGraphviz(std::ostream& os) const override { - os << GraphViz::Node{.id = name(), .shape = GraphViz::Shape::InvTrapezium}; - BlueprintNode::addToGraphviz(os); + const std::string& getName() const { return m_name; } + + MaterialDesignatorBlueprintNode& setName(std::string name) { + m_name = std::move(name); + return *this; } private: - std::string m_name; - std::string m_material; + std::string m_name{}; + + std::optional m_binning{}; }; } // namespace Acts diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index 9d7894d4ba5..a35c1ecf2d6 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -102,9 +102,10 @@ CylinderContainerBlueprintNode& BlueprintNode::addCylinderContainer( } MaterialDesignatorBlueprintNode& BlueprintNode::addMaterial( + const std::string& name, const std::function& callback) { - auto material = std::make_shared(); + auto material = std::make_shared(name); addChild(material); if (callback) { callback(*material); diff --git a/Core/src/Geometry/CMakeLists.txt b/Core/src/Geometry/CMakeLists.txt index 06a71b8cbc6..9a7ebc2a9a3 100644 --- a/Core/src/Geometry/CMakeLists.txt +++ b/Core/src/Geometry/CMakeLists.txt @@ -48,4 +48,5 @@ target_sources( CylinderContainerBlueprintNode.cpp StaticBlueprintNode.cpp LayerBlueprintNode.cpp + MaterialDesignatorBlueprintNode.cpp ) diff --git a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp new file mode 100644 index 00000000000..b495aee9cea --- /dev/null +++ b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp @@ -0,0 +1,143 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" + +#include "Acts/Detector/ProtoBinning.hpp" +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/Portal.hpp" +#include "Acts/Material/ProtoSurfaceMaterial.hpp" +#include "Acts/Surfaces/Surface.hpp" +#include "Acts/Utilities/GraphViz.hpp" +#include "Acts/Utilities/Helpers.hpp" + +namespace Acts { + +const std::string& MaterialDesignatorBlueprintNode::name() const { + return m_name; +} + +void MaterialDesignatorBlueprintNode::toStream(std::ostream& os) const { + os << "MaterialDesignatorBlueprintNode(" << name() << ")"; +} + +Volume& MaterialDesignatorBlueprintNode::build(const Options& options, + const GeometryContext& gctx, + const Logger& logger) { + if (children().size() != 1) { + ACTS_ERROR(prefix() << "MaterialDesignatorBlueprintNode must have exactly " + "one child, but has " + << children().size()); + throw std::runtime_error( + "MaterialDesignatorBlueprintNode must have exactly one child"); + } + return children().at(0).build(options, gctx, logger); +} + +PortalShellBase& MaterialDesignatorBlueprintNode::connect( + const Options& options, const GeometryContext& gctx, const Logger& logger) { + ACTS_DEBUG(prefix() << "MaterialDesignatorBlueprintNode::connect"); + if (children().size() != 1) { + ACTS_ERROR(prefix() << "MaterialDesignatorBlueprintNode must have exactly " + "one child, but has " + << children().size()); + throw std::runtime_error( + "MaterialDesignatorBlueprintNode must have exactly one child"); + } + if (!m_binning) { + ACTS_ERROR(prefix() << "Binning is not set"); + throw std::runtime_error("Binning is not set"); + } + + auto& shell = children().at(0).connect(options, gctx, logger); + + ACTS_DEBUG(prefix() << "Received shell from child " + << children().at(0).name()); + + if (auto* cylShell = dynamic_cast(&shell)) { + ACTS_DEBUG(prefix() << "Connecting cylinder shell"); + + std::visit( + overloaded{ + [&](const std::vector>& binning) { + ACTS_DEBUG(prefix() << "Binning is set to compatible type"); + using enum CylinderVolumeBounds::Face; + + for (auto& [face, loc0, loc1] : binning) { + if (face == OuterCylinder || face == InnerCylinder) { + if (loc0.binValue != BinningValue::binRPhi) { + ACTS_ERROR(prefix() << "Binning is not in RPhi"); + throw std::runtime_error("Binning is not in RPhi"); + } + + if (loc1.binValue != BinningValue::binZ) { + ACTS_ERROR(prefix() << "Binning is not in Z"); + throw std::runtime_error("Binning is not in Z"); + } + } + + if (face == PositiveDisc || face == NegativeDisc) { + if (loc0.binValue != BinningValue::binPhi) { + ACTS_ERROR(prefix() << "Binning is not in Phi"); + throw std::runtime_error("Binning is not in Phi"); + } + if (loc1.binValue != BinningValue::binR) { + ACTS_ERROR(prefix() << "Binning is not in R"); + throw std::runtime_error("Binning is not in R"); + } + } + + Experimental::BinningDescription desc{.binning = {loc0, loc1}}; + ACTS_DEBUG(prefix() << "~> Assigning proto binning " + << desc.toString() << " to face " << face); + + auto material = + std::make_shared(std::move(desc)); + + auto portal = cylShell->portal(face); + if (portal == nullptr) { + ACTS_ERROR(prefix() << "Portal is nullptr"); + throw std::runtime_error("Portal is nullptr"); + } + portal->surface().assignSurfaceMaterial(std::move(material)); + } + }, + [&](const auto& /*binning*/) { + ACTS_ERROR(prefix() << "Binning is set to unknown type"); + throw std::runtime_error("Unknown binning type"); + }, + }, + m_binning.value()); + } + // @TODO: Handle cuboid volume shell + else { + ACTS_ERROR(prefix() << "Shell is not supported"); + throw std::runtime_error("Shell is not supported"); + } + + return shell; +} + +void MaterialDesignatorBlueprintNode::finalize(const Options& options, + TrackingVolume& parent, + const Logger& logger) { + if (children().size() != 1) { + throw std::runtime_error( + "MaterialDesignatorBlueprintNode must have exactly one child"); + } + return children().at(0).finalize(options, parent, logger); +} + +void MaterialDesignatorBlueprintNode::addToGraphviz(std::ostream& os) const { + os << GraphViz::Node{.id = name(), .shape = GraphViz::Shape::InvTrapezium}; + BlueprintNode::addToGraphviz(os); +} + +} // namespace Acts diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 903f4c15897..bd94958437d 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -46,7 +46,7 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, ACTS_LOCAL_LOGGER(getDefaultLogger("pseudoNavigation", logLevel)); std::ofstream csv{path}; - csv << "x,y,z,volume,boundary,sensitive" << std::endl; + csv << "x,y,z,volume,boundary,sensitive,material" << std::endl; std::mt19937 rnd{42}; @@ -89,10 +89,22 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, csv << "," << volume->geometryId().volume(); csv << "," << volume->geometryId().boundary(); csv << "," << volume->geometryId().sensitive(); + csv << "," << 0; csv << std::endl; ACTS_VERBOSE("start pseudo navigation"); + auto writeIntersection = [&](const Vector3& position, + const Surface& surface) { + csv << run << "," << position[0] << "," << position[1] << "," + << position[2]; + csv << "," << surface.geometryId().volume(); + csv << "," << surface.geometryId().boundary(); + csv << "," << surface.geometryId().sensitive(); + csv << "," << (surface.surfaceMaterial() != nullptr ? 1 : 0); + csv << std::endl; + }; + for (std::size_t i = 0; i < 100; i++) { assert(currentVolume != nullptr); main = NavigationStream{}; @@ -122,29 +134,23 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, ACTS_VERBOSE( "Already on surface at initialization, skipping candidate"); - auto id = main.currentCandidate().surface().geometryId(); - csv << run << "," << position[0] << "," << position[1] << "," - << position[2]; - csv << "," << id.volume(); - csv << "," << id.boundary(); - csv << "," << id.sensitive(); - csv << std::endl; + // auto id = main.currentCandidate().surface().geometryId(); + // csv << run << "," << position[0] << "," << position[1] << "," + // << position[2]; + // csv << "," << id.volume(); + // csv << "," << id.boundary(); + // csv << "," << id.sensitive(); + + // csv << std::endl; + + writeIntersection(position, main.currentCandidate().surface()); + if (!main.switchToNextCandidate()) { ACTS_WARNING("candidates exhausted unexpectedly"); break; } } - auto writeIntersection = [&](const Vector3& position, - const Surface& surface) { - csv << run << "," << position[0] << "," << position[1] << "," - << position[2]; - csv << "," << surface.geometryId().volume(); - csv << "," << surface.geometryId().boundary(); - csv << "," << surface.geometryId().sensitive(); - csv << std::endl; - }; - bool terminated = false; while (main.remainingCandidates() > 0) { const auto& candidate = main.currentCandidate(); @@ -167,7 +173,7 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, csv << run << "," << subpos[0] << "," << subpos[1] << "," << subpos[2]; csv << "," << currentVolume->geometryId().volume(); - csv << ",0,0"; // zero boundary and sensitive ids + csv << ",0,0,0"; // zero boundary and sensitive ids csv << std::endl; } @@ -369,24 +375,28 @@ void addBlueprint(Context& ctx) { py::arg("name"), py::arg("direction")); auto matNode = - py::class_>( + py::class_>( m, "MaterialDesignatorBlueprintNode") - .def(py::init(), - "name"_a, "binning"_a); + .def(py::init(), "name"_a) + .def_property("name", &MaterialDesignatorBlueprintNode::name, + &MaterialDesignatorBlueprintNode::setName) + .def_property("binning", &MaterialDesignatorBlueprintNode::binning, + &MaterialDesignatorBlueprintNode::setBinning); + + // py::class_(matNode, + // "BinningConfig"); addContextManagerProtocol(matNode); addNodeMethods( "Material", - [](BlueprintNode& self, const std::string& name, - const Experimental::ProtoBinning& binning) { - auto child = - std::make_shared(name, binning); + [](BlueprintNode& self, const std::string& name) { + auto child = std::make_shared(name); self.addChild(child); return child; }, - "name"_a, "binning"_a); + "name"_a); auto layerNode = py::class_ Date: Wed, 9 Oct 2024 17:38:22 +0200 Subject: [PATCH 042/100] blueprint: Material node graphviz shape change --- .../MaterialDesignatorBlueprintNode.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp index b495aee9cea..f908c2ae2f4 100644 --- a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp +++ b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp @@ -136,7 +136,25 @@ void MaterialDesignatorBlueprintNode::finalize(const Options& options, } void MaterialDesignatorBlueprintNode::addToGraphviz(std::ostream& os) const { - os << GraphViz::Node{.id = name(), .shape = GraphViz::Shape::InvTrapezium}; + std::stringstream ss; + ss << "" + name() + ""; + ss << "
CylinderContainer"; + + std::visit( + overloaded{ + [&](const std::vector< + std::tuple>& binning) { + for (const auto& [face, loc0, loc1] : binning) { + ss << "
" << face; + ss << ": " << loc0.binValue << "=" << loc0.bins(); + ss << ", " << loc1.binValue << "=" << loc1.bins(); + } + }, + [&](const auto& /*binning*/) {}}, + m_binning.value()); + os << GraphViz::Node{ + .id = name(), .label = ss.str(), .shape = GraphViz::Shape::Hexagon}; BlueprintNode::addToGraphviz(os); } From 38a70b2a5217beb440e0fe9d8bf1ff736de44d80 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Thu, 10 Oct 2024 17:14:14 +0200 Subject: [PATCH 043/100] blueprint: material node name --- Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index 77596a4ea3d..3cdd5ed3918 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -29,6 +29,7 @@ #include "Acts/Visualization/GeometryView3D.hpp" #include "Acts/Visualization/ObjVisualization3D.hpp" +#include #include #include @@ -365,7 +366,7 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { cfg.envelope[BinningValue::binR] = {0_mm, 20_mm}; auto root = std::make_unique(cfg); - root->addMaterial([&](auto& mat) { + root->addMaterial("GlobalMaterial", [&](auto& mat) { mat.addCylinderContainer("Detector", BinningValue::binR, [&](auto& det) { det.addCylinderContainer("Pixel", BinningValue::binZ, [&](auto& cyl) { cyl.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) From eca6dc7e2d13453af16729cb1b9649b397802110 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Sat, 12 Oct 2024 10:20:33 +0200 Subject: [PATCH 044/100] blueprint: Finalize gets geocontext as well --- Core/include/Acts/Geometry/BlueprintNode.hpp | 3 ++- Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp | 4 ++-- Core/include/Acts/Geometry/LayerBlueprintNode.hpp | 3 ++- .../include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp | 4 ++-- Core/include/Acts/Geometry/RootBlueprintNode.hpp | 3 ++- Core/include/Acts/Geometry/StaticBlueprintNode.hpp | 3 ++- Core/src/Geometry/CylinderContainerBlueprintNode.cpp | 3 ++- Core/src/Geometry/LayerBlueprintNode.cpp | 3 ++- Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp | 3 ++- Core/src/Geometry/RootBlueprintNode.cpp | 3 ++- Core/src/Geometry/StaticBlueprintNode.cpp | 3 ++- 11 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index 2630b2729c3..6cae41bdeb6 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -59,7 +59,8 @@ class BlueprintNode { const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) = 0; - virtual void finalize(const Options& options, TrackingVolume& parent, + virtual void finalize(const Options& options, const GeometryContext& gctx, + TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) = 0; StaticBlueprintNode& addStaticVolume( diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index 6faca235401..9e18fb4f579 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -38,8 +38,8 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(const Options& options, TrackingVolume& parent, - const Logger& logger) override; + void finalize(const Options& options, const GeometryContext& gctx, + TrackingVolume& parent, const Logger& logger) override; CylinderContainerBlueprintNode& setDirection(BinningValue direction); CylinderContainerBlueprintNode& setAttachmentStrategy( diff --git a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp index 9ea5298b0ba..19ae38a738a 100644 --- a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp @@ -26,7 +26,8 @@ class LayerBlueprintNode : public StaticBlueprintNode { Volume& build(const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(const Options& options, TrackingVolume& parent, + void finalize(const Options& options, const GeometryContext& gctx, + TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override; LayerBlueprintNode& setSurfaces( diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index 532b8428a1b..96e082d5f5b 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -38,8 +38,8 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(const Options& options, TrackingVolume& parent, - const Logger& logger) override; + void finalize(const Options& options, const GeometryContext& gctx, + TrackingVolume& parent, const Logger& logger) override; void addToGraphviz(std::ostream& os) const override; diff --git a/Core/include/Acts/Geometry/RootBlueprintNode.hpp b/Core/include/Acts/Geometry/RootBlueprintNode.hpp index 39afdb22467..1f91af4812a 100644 --- a/Core/include/Acts/Geometry/RootBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/RootBlueprintNode.hpp @@ -40,7 +40,8 @@ class RootBlueprintNode : public BlueprintNode { const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(const Options& options, TrackingVolume& parent, + void finalize(const Options& options, const GeometryContext& gctx, + TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override; void addToGraphviz(std::ostream& os) const override; diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index 60528ab3830..1f4eebc2aa5 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -29,7 +29,8 @@ class StaticBlueprintNode : public BlueprintNode { const Options& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(const Options& options, TrackingVolume& parent, + void finalize(const Options& options, const GeometryContext& gctx, + TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override; protected: diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 533f9a2b2c6..850d05e95a2 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -146,6 +146,7 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( } void CylinderContainerBlueprintNode::finalize(const Options& options, + const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) { ACTS_DEBUG(prefix() << "Finalizing cylinder container"); @@ -176,7 +177,7 @@ void CylinderContainerBlueprintNode::finalize(const Options& options, ACTS_DEBUG(prefix() << "Finalizing " << children().size() << " children"); for (auto& child : children()) { - child.finalize(options, parent, logger); + child.finalize(options, gctx, parent, logger); } } diff --git a/Core/src/Geometry/LayerBlueprintNode.cpp b/Core/src/Geometry/LayerBlueprintNode.cpp index 9eb1af43035..24c87cb61eb 100644 --- a/Core/src/Geometry/LayerBlueprintNode.cpp +++ b/Core/src/Geometry/LayerBlueprintNode.cpp @@ -89,9 +89,10 @@ void LayerBlueprintNode::buildVolume(const Extent& extent, } void LayerBlueprintNode::finalize(const BlueprintNode::Options& options, + const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) { - StaticBlueprintNode::finalize(options, parent, logger); + StaticBlueprintNode::finalize(options, gctx, parent, logger); } const std::string& LayerBlueprintNode::name() const { diff --git a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp index f908c2ae2f4..7f673dd281a 100644 --- a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp +++ b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp @@ -126,13 +126,14 @@ PortalShellBase& MaterialDesignatorBlueprintNode::connect( } void MaterialDesignatorBlueprintNode::finalize(const Options& options, + const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) { if (children().size() != 1) { throw std::runtime_error( "MaterialDesignatorBlueprintNode must have exactly one child"); } - return children().at(0).finalize(options, parent, logger); + return children().at(0).finalize(options, gctx, parent, logger); } void MaterialDesignatorBlueprintNode::addToGraphviz(std::ostream& os) const { diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index aa99fad2d96..20786dd9938 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -38,6 +38,7 @@ PortalShellBase &RootBlueprintNode::connect(const Options & /*options*/, } void RootBlueprintNode::finalize(const Options & /*options*/, + const GeometryContext & /*gctx*/, TrackingVolume & /*parent*/, const Logger & /*logger*/) { throw std::logic_error("Root node cannot be finalized"); @@ -128,7 +129,7 @@ std::unique_ptr RootBlueprintNode::construct( shell.connectOuter(*world); - child.finalize(options, *world, logger); + child.finalize(options, gctx, *world, logger); // @TODO: Handle material decorator, geo id hook // @TODO: Maybe add a name uniqueness check diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index fb12108047a..53f5f62288a 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -74,6 +74,7 @@ PortalShellBase& StaticBlueprintNode::connect(const Options& options, } void StaticBlueprintNode::finalize(const Options& options, + const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) { ACTS_DEBUG(prefix() << "Finalizing static volume"); @@ -89,7 +90,7 @@ void StaticBlueprintNode::finalize(const Options& options, } for (auto& child : children()) { - child.finalize(options, *m_volume, logger); + child.finalize(options, gctx, *m_volume, logger); } ACTS_DEBUG(prefix() << "Registering " << m_shell->size() From 45e43ad8ef509d726637ade5347841e20df6d460 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 15 Oct 2024 14:01:48 +0200 Subject: [PATCH 045/100] blueprint: Adjust to nav policy factory signature change --- Core/src/Geometry/CylinderContainerBlueprintNode.cpp | 2 +- Core/src/Geometry/RootBlueprintNode.cpp | 2 +- Core/src/Geometry/StaticBlueprintNode.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 850d05e95a2..cf88fbb33f1 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -168,7 +168,7 @@ void CylinderContainerBlueprintNode::finalize(const Options& options, << " gap volumes with parent"); for (auto& [shell, gap] : m_gaps) { std::cout << "~> " << gap->volumeName() << std::endl; - gap->setNavigationPolicy(policyFactory->build(*gap)); + gap->setNavigationPolicy(policyFactory->build(gctx, *gap, logger)); parent.addVolume(std::move(gap)); shell->applyToVolume(); diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index 20786dd9938..0722fcb0577 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -119,7 +119,7 @@ std::unique_ptr RootBlueprintNode::construct( // @TODO: This needs to become configurable world->setNavigationPolicy( - options.defaultNavigationPolicyFactory->build(*world)); + options.defaultNavigationPolicyFactory->build(gctx, *world, logger)); // Need one-sided portal shell that connects outwards to nullptr SingleCylinderPortalShell worldShell{*world}; diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index 53f5f62288a..98270a6a72c 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -102,7 +102,7 @@ void StaticBlueprintNode::finalize(const Options& options, // @TODO: This needs to become configurable m_volume->setNavigationPolicy( - options.defaultNavigationPolicyFactory->build(*m_volume)); + options.defaultNavigationPolicyFactory->build(gctx, *m_volume, logger)); parent.addVolume(std::move(m_volume)); } From b05e2215f522dc8e8ac3ed2a60f66e6c300fb6d8 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Sat, 12 Oct 2024 14:44:32 +0200 Subject: [PATCH 046/100] blueprint: enum renaming --- Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index 96e082d5f5b..f099318cda4 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -22,7 +22,7 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { // @TODO: This needs cuboid volume storage as well // @TODO: I don't love the type using BinningConfig = std::variant>>; MaterialDesignatorBlueprintNode(const std::string& name) : m_name(name) {} From ca68b00c22437df99e597752a1789ec2725c937b Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Sat, 12 Oct 2024 14:44:41 +0200 Subject: [PATCH 047/100] blueprint: Material node fixes --- .../Geometry/MaterialDesignatorBlueprintNode.cpp | 4 ++++ .../UnitTests/Core/Geometry/BlueprintNodeTests.cpp | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp index 7f673dd281a..ed6eb58fb66 100644 --- a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp +++ b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp @@ -137,6 +137,10 @@ void MaterialDesignatorBlueprintNode::finalize(const Options& options, } void MaterialDesignatorBlueprintNode::addToGraphviz(std::ostream& os) const { + if (!m_binning) { + throw std::runtime_error("Binning is not set"); + } + std::stringstream ss; ss << "" + name() + ""; ss << "
CylinderContainer"; diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index 3cdd5ed3918..d1ddae075a0 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -13,6 +13,7 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/Units.hpp" +#include "Acts/Detector/ProtoBinning.hpp" #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/CylinderVolumeBounds.hpp" #include "Acts/Geometry/GeometryContext.hpp" @@ -366,7 +367,17 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { cfg.envelope[BinningValue::binR] = {0_mm, 20_mm}; auto root = std::make_unique(cfg); - root->addMaterial("GlobalMaterial", [&](auto& mat) { + root->addMaterial("GlobalMaterial", [&](MaterialDesignatorBlueprintNode& + mat) { + Experimental::ProtoBinning zBinning{BinningValue::binZ, + AxisBoundaryType::Bound, 20}; + + Experimental::ProtoBinning rPhiBinning{BinningValue::binRPhi, + AxisBoundaryType::Bound, 20}; + + mat.setBinning(std::vector{std::tuple{ + CylinderVolumeBounds::Face::OuterCylinder, rPhiBinning, zBinning}}); + mat.addCylinderContainer("Detector", BinningValue::binR, [&](auto& det) { det.addCylinderContainer("Pixel", BinningValue::binZ, [&](auto& cyl) { cyl.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) From f33977c7b4945b72c3a573cfd3e56a7778df1b76 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 14 Oct 2024 16:35:55 +0200 Subject: [PATCH 048/100] blueprint: Layer/Static nodes get policy override --- .../Acts/Geometry/LayerBlueprintNode.hpp | 6 ++++++ .../Acts/Geometry/StaticBlueprintNode.hpp | 7 +++++++ Core/src/Geometry/LayerBlueprintNode.cpp | 11 ++++++++++ Core/src/Geometry/StaticBlueprintNode.cpp | 20 ++++++++++++++++--- 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp index 19ae38a738a..1d8bb98be8c 100644 --- a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp @@ -47,6 +47,12 @@ class LayerBlueprintNode : public StaticBlueprintNode { const LayerType& layerType() const; + LayerBlueprintNode& setNavigationPolicyFactory( + std::shared_ptr navigationPolicyFactory) + override; + + const NavigationPolicyFactory* navigationPolicyFactory() const; + void addToGraphviz(std::ostream& os) const override; private: diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index 1f4eebc2aa5..136996e4281 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -33,12 +33,19 @@ class StaticBlueprintNode : public BlueprintNode { TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override; + virtual StaticBlueprintNode& setNavigationPolicyFactory( + std::shared_ptr navigationPolicyFactory); + + const NavigationPolicyFactory* navigationPolicyFactory() const; + protected: void addToGraphviz(std::ostream& os) const override; std::unique_ptr m_volume; std::unique_ptr m_shell; + + std::shared_ptr m_navigationPolicyFactory = nullptr; }; } // namespace Acts diff --git a/Core/src/Geometry/LayerBlueprintNode.cpp b/Core/src/Geometry/LayerBlueprintNode.cpp index 24c87cb61eb..dbf0439a6ec 100644 --- a/Core/src/Geometry/LayerBlueprintNode.cpp +++ b/Core/src/Geometry/LayerBlueprintNode.cpp @@ -139,6 +139,17 @@ const LayerBlueprintNode::LayerType& LayerBlueprintNode::layerType() const { return m_layerType; } +LayerBlueprintNode& LayerBlueprintNode::setNavigationPolicyFactory( + std::shared_ptr navigationPolicyFactory) { + m_navigationPolicyFactory = std::move(navigationPolicyFactory); + return *this; +} + +const NavigationPolicyFactory* LayerBlueprintNode::navigationPolicyFactory() + const { + return m_navigationPolicyFactory.get(); +} + void LayerBlueprintNode::addToGraphviz(std::ostream& os) const { std::stringstream ss; ss << "" << name() << ""; diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index 98270a6a72c..89725404e6f 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -100,9 +100,12 @@ void StaticBlueprintNode::finalize(const Options& options, ACTS_DEBUG(prefix() << " Adding volume (" << m_volume->volumeName() << ") to parent volume (" << parent.volumeName() << ")"); - // @TODO: This needs to become configurable - m_volume->setNavigationPolicy( - options.defaultNavigationPolicyFactory->build(gctx, *m_volume, logger)); + const auto* policyFactory = options.defaultNavigationPolicyFactory.get(); + + if (m_navigationPolicyFactory) { + policyFactory = m_navigationPolicyFactory.get(); + } + m_volume->setNavigationPolicy(policyFactory->build(gctx, *m_volume, logger)); parent.addVolume(std::move(m_volume)); } @@ -115,6 +118,17 @@ const std::string& StaticBlueprintNode::name() const { return m_volume->volumeName(); } +StaticBlueprintNode& StaticBlueprintNode::setNavigationPolicyFactory( + std::shared_ptr navigationPolicyFactory) { + m_navigationPolicyFactory = std::move(navigationPolicyFactory); + return *this; +} + +const NavigationPolicyFactory* StaticBlueprintNode::navigationPolicyFactory() + const { + return m_navigationPolicyFactory.get(); +} + void StaticBlueprintNode::addToGraphviz(std::ostream& os) const { std::stringstream ss; ss << "" << name() << ""; From 6244bb8fb62522756a955c3d74437c631f136513 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 15 Oct 2024 14:04:21 +0200 Subject: [PATCH 049/100] blueprint: Add logger to NavArgs --- Examples/Python/src/Blueprint.cpp | 6 ++++-- Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index bd94958437d..09dcede7c34 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -109,8 +109,10 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, assert(currentVolume != nullptr); main = NavigationStream{}; - currentVolume->updateNavigationState( - {.main = main, .position = position, .direction = direction}); + currentVolume->updateNavigationState({.main = main, + .position = position, + .direction = direction, + .logger = logger()}); ACTS_VERBOSE(main.candidates().size() << " candidates"); diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index d1ddae075a0..cf7ceaea5e3 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -208,8 +208,10 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, for (std::size_t i = 0; i < 100; i++) { main = NavigationStream{}; - currentVolume->updateNavigationState( - {.main = main, .position = position, .direction = direction}); + currentVolume->updateNavigationState({.main = main, + .position = position, + .direction = direction, + .logger = logger}); ACTS_VERBOSE(main.candidates().size() << " candidates"); From 94275317216664a81e0a61e550e12782feaac14d Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 14 Oct 2024 16:39:54 +0200 Subject: [PATCH 050/100] blueprint: Allow setting policy from python --- Examples/Python/src/Blueprint.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 09dcede7c34..4733269c8b1 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -325,7 +325,10 @@ void addBlueprint(Context& ctx) { name)); }), py::arg("transform"), py::arg("bounds"), - py::arg("name") = "undefined"); + py::arg("name") = "undefined") + .def_property("navigationPolicyFactory", + &Acts::StaticBlueprintNode::navigationPolicyFactory, + &Acts::StaticBlueprintNode::setNavigationPolicyFactory); addContextManagerProtocol(staticNode); @@ -386,9 +389,6 @@ void addBlueprint(Context& ctx) { .def_property("binning", &MaterialDesignatorBlueprintNode::binning, &MaterialDesignatorBlueprintNode::setBinning); - // py::class_(matNode, - // "BinningConfig"); - addContextManagerProtocol(matNode); addNodeMethods( @@ -401,7 +401,7 @@ void addBlueprint(Context& ctx) { "name"_a); auto layerNode = - py::class_>( m, "LayerBlueprintNode") .def(py::init(), py::arg("name")) @@ -413,7 +413,10 @@ void addBlueprint(Context& ctx) { .def_property("envelope", &Acts::LayerBlueprintNode::envelope, &Acts::LayerBlueprintNode::setEnvelope) .def_property("layerType", &Acts::LayerBlueprintNode::layerType, - &Acts::LayerBlueprintNode::setLayerType); + &Acts::LayerBlueprintNode::setLayerType) + .def_property("navigationPolicyFactory", + &Acts::LayerBlueprintNode::navigationPolicyFactory, + &Acts::LayerBlueprintNode::setNavigationPolicyFactory); py::enum_(layerNode, "LayerType") .value("Cylinder", Acts::LayerBlueprintNode::LayerType::Cylinder) From fc60908b13d999e973ab5011a4c7cf92c06f1162 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 15 Oct 2024 17:29:04 +0200 Subject: [PATCH 051/100] blueprint: Downgrade WARNINGs for non-problematic merges --- Core/src/Geometry/PortalLinkBase.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/src/Geometry/PortalLinkBase.cpp b/Core/src/Geometry/PortalLinkBase.cpp index bdc65f8a552..f558fe19238 100644 --- a/Core/src/Geometry/PortalLinkBase.cpp +++ b/Core/src/Geometry/PortalLinkBase.cpp @@ -109,7 +109,7 @@ std::unique_ptr PortalLinkBase::merge( } else if (const auto* bTrivial = dynamic_cast(b.get()); bTrivial != nullptr) { - ACTS_VERBOSE( + ACTS_WARNING( "Merging a grid portal with a trivial portal (via composite)"); return std::make_unique(std::move(a), std::move(b), direction); @@ -128,7 +128,7 @@ std::unique_ptr PortalLinkBase::merge( aTrivial != nullptr) { if (const auto* bGrid = dynamic_cast(b.get()); bGrid) { - ACTS_VERBOSE( + ACTS_WARNING( "Merging a trivial portal with a grid portal (via composite)"); return std::make_unique(std::move(a), std::move(b), direction); @@ -141,7 +141,7 @@ std::unique_ptr PortalLinkBase::merge( direction); } else if (dynamic_cast(b.get()) != nullptr) { - ACTS_WARNING("Merging a trivial portal with a composite portal"); + ACTS_VERBOSE("Merging a trivial portal with a composite portal"); return std::make_unique(std::move(a), std::move(b), direction); @@ -156,12 +156,12 @@ std::unique_ptr PortalLinkBase::merge( direction); } else if (dynamic_cast(b.get()) != nullptr) { - ACTS_WARNING("Merging a composite portal with a trivial portal"); + ACTS_VERBOSE("Merging a composite portal with a trivial portal"); return std::make_unique(std::move(a), std::move(b), direction); } else if (dynamic_cast(b.get()) != nullptr) { - ACTS_WARNING("Merging two composite portals"); + ACTS_VERBOSE("Merging two composite portals"); return std::make_unique(std::move(a), std::move(b), direction); From 5b574d45896473d87b1f02bf26e85db167dbcf8c Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 16 Oct 2024 09:25:24 +0200 Subject: [PATCH 052/100] blueprint: add clearChildren to node --- Core/include/Acts/Geometry/BlueprintNode.hpp | 2 + Core/src/Geometry/BlueprintNode.cpp | 4 + Core/src/Geometry/RootBlueprintNode.cpp | 2 +- Core/src/Geometry/StaticBlueprintNode.cpp | 3 + Examples/Python/src/Blueprint.cpp | 1 + Examples/Python/tests/test_blueprint.py | 89 ++++++++++++++++++++ 6 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 Examples/Python/tests/test_blueprint.py diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index 6cae41bdeb6..7ffeb044dd6 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -99,6 +99,8 @@ class BlueprintNode { MutableChildRange children(); ChildRange children() const; + void clearChildren(); + std::size_t depth() const; void graphViz(std::ostream& os) const; diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index a35c1ecf2d6..c747b614171 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -124,6 +124,10 @@ LayerBlueprintNode& BlueprintNode::addLayer( return *layer; } +void BlueprintNode::clearChildren() { + m_children.clear(); +} + void BlueprintNode::graphViz(std::ostream& os) const { os << "digraph BlueprintNode {" << std::endl; addToGraphviz(os); diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index 0722fcb0577..af64d0c3465 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -46,7 +46,7 @@ void RootBlueprintNode::finalize(const Options & /*options*/, void RootBlueprintNode::addToGraphviz(std::ostream &os) const { GraphViz::Node node{ - .id = name(), .label = "Root", .shape = GraphViz::Shape::House}; + .id = name(), .label = "World", .shape = GraphViz::Shape::House}; os << node; BlueprintNode::addToGraphviz(os); diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index 89725404e6f..49ca1b56d55 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -133,6 +133,9 @@ void StaticBlueprintNode::addToGraphviz(std::ostream& os) const { std::stringstream ss; ss << "" << name() << ""; ss << "
"; + if (m_volume == nullptr) { + throw std::runtime_error("Volume is not built"); + } switch (m_volume->volumeBounds().type()) { case VolumeBounds::eCylinder: ss << "Cylinder"; diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 4733269c8b1..37a5414c633 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -251,6 +251,7 @@ void addBlueprint(Context& ctx) { .def("addChild", &BlueprintNode::addChild) .def_property_readonly("children", py::overload_cast<>(&BlueprintNode::children)) + .def("clearChildren", &BlueprintNode::clearChildren) .def_property_readonly("name", &BlueprintNode::name) .def("graphViz", [](BlueprintNode& self, const py::object& fh) { std::stringstream ss; diff --git a/Examples/Python/tests/test_blueprint.py b/Examples/Python/tests/test_blueprint.py new file mode 100644 index 00000000000..efeb3eedd63 --- /dev/null +++ b/Examples/Python/tests/test_blueprint.py @@ -0,0 +1,89 @@ +import pytest + +import acts + +mm = acts.UnitConstants.mm +m = acts.UnitConstants.m +degree = acts.UnitConstants.degree + +bv = acts.BinningValue + +gctx = acts.GeometryContext() +logLevel = acts.logging.VERBOSE + + +def test_zdirection_container_blueprint(tmp_path): + + def write(root: acts.BlueprintNode, stage: int): + gz = tmp_path / f"blueprint_{stage}.dot" + print(gz) + with gz.open("w") as fh: + root.graphViz(fh) + + base = acts.Transform3.Identity() + + root = acts.RootBlueprintNode(envelope=acts.ExtentEnvelope(r=[10 * mm, 10 * mm])) + + barrel = root.addCylinderContainer("Barrel", direction=bv.binR) + + r = 25 * mm + for i in range(1, 3): + r += 50 * mm + bounds = acts.CylinderVolumeBounds(r, r + 20 * mm, 200 * mm) + barrel.addStaticVolume(base, bounds, name=f"Barrel_{i}") + + write(barrel, 1) + + root.clearChildren() + + det = root.addCylinderContainer("Detector", direction=bv.binZ) + + with det.CylinderContainer("nEC", direction=bv.binZ) as ec: + z = -200 + for i in range(1, 3): + z -= 200 * mm + bounds = acts.CylinderVolumeBounds(100 * mm, 150 * mm, 50 * mm) + + trf = base * acts.Translation3(acts.Vector3(0, 0, z)) + + ec.addStaticVolume(trf, bounds, name=f"nEC_{i}") + + write(ec, 2) + + det.addChild(barrel) + + write(det, 3) + + with det.CylinderContainer("pEC", direction=bv.binZ) as ec: + z = 200 + for i in range(1, 3): + z += 200 * mm + bounds = acts.CylinderVolumeBounds(100 * mm, 150 * mm, 50 * mm) + + trf = base * acts.Translation3(acts.Vector3(0, 0, z)) + + ec.addStaticVolume(trf, bounds, name=f"pEC_{i}") + + write(root, 4) + + # gz = tmp_path / "blueprint.dot" + # print(gz) + # with gz.open("w") as fh: + # root.graphViz(fh) + # + # trackingGeometry = root.construct( + # acts.BlueprintNode.Options(), gctx, level=logLevel + # ) + # assert trackingGeometry is not None + + +if False: + with root.CylinderContainer("Detector", direction=bv.binZ) as det: + det.addStaticVolume( + base, acts.CylinderVolumeBounds(0, 23 * mm, 3 * m), "BeamPipe" + ) + + trackingGeometry = root.construct( + acts.BlueprintNode.Options(), gctx, level=logLevel + ) + assert trackingGeometry is not None From 02bbada08b53bf8f1c8d095b6128ef9886dd8c56 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 6 Nov 2024 15:27:57 +0100 Subject: [PATCH 053/100] blueprint: connectOuter -> fill --- Core/src/Geometry/CylinderContainerBlueprintNode.cpp | 3 +-- Core/src/Geometry/RootBlueprintNode.cpp | 2 +- Core/src/Geometry/StaticBlueprintNode.cpp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index cf88fbb33f1..649fd71ccbe 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -168,10 +168,9 @@ void CylinderContainerBlueprintNode::finalize(const Options& options, << " gap volumes with parent"); for (auto& [shell, gap] : m_gaps) { std::cout << "~> " << gap->volumeName() << std::endl; - gap->setNavigationPolicy(policyFactory->build(gctx, *gap, logger)); - parent.addVolume(std::move(gap)); shell->applyToVolume(); + gap->setNavigationPolicy(policyFactory->build(gctx, *gap, logger)); } ACTS_DEBUG(prefix() << "Finalizing " << children().size() << " children"); diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index af64d0c3465..20a23da2ef8 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -127,7 +127,7 @@ std::unique_ptr RootBlueprintNode::construct( auto &shell = child.connect(options, gctx, logger); - shell.connectOuter(*world); + shell.fill(*world); child.finalize(options, gctx, *world, logger); diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index 49ca1b56d55..c227fa8e1b8 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -52,7 +52,7 @@ PortalShellBase& StaticBlueprintNode::connect(const Options& options, for (auto& child : children()) { auto& shell = child.connect(options, gctx, logger); // Register ourselves on the outside of the shell - shell.connectOuter(*m_volume); + shell.fill(*m_volume); } VolumeBounds::BoundsType type = m_volume->volumeBounds().type(); From a456bb73307f91378568e5e7dcca94c781b76f8d Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 18 Oct 2024 10:22:43 +0200 Subject: [PATCH 054/100] blueprint: Fix incorrect dynamic cast ifs --- Core/src/Geometry/RootBlueprintNode.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/RootBlueprintNode.cpp index 20a23da2ef8..83e6cefd40e 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/RootBlueprintNode.cpp @@ -83,7 +83,8 @@ std::unique_ptr RootBlueprintNode::construct( std::shared_ptr worldBounds; - if (const auto *cyl = dynamic_cast(&bounds)) { + if (const auto *cyl = dynamic_cast(&bounds); + cyl != nullptr) { using enum CylinderVolumeBounds::BoundValues; // Make a copy that we'll modify @@ -106,7 +107,8 @@ std::unique_ptr RootBlueprintNode::construct( worldBounds = std::move(newBounds); } else if (const auto *box = - dynamic_cast(&bounds)) { + dynamic_cast(&bounds); + box != nullptr) { throw std::logic_error{"Not implemented"}; } else { throw std::logic_error{"Unsupported volume bounds type"}; From 25b152b6965bf2518e76b943f351ee657c033581 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 18 Oct 2024 10:23:01 +0200 Subject: [PATCH 055/100] blueprint: Fix shadowing --- Examples/Python/src/Blueprint.cpp | 6 ++---- Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 37a5414c633..89a13ac4c42 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -94,10 +94,8 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, ACTS_VERBOSE("start pseudo navigation"); - auto writeIntersection = [&](const Vector3& position, - const Surface& surface) { - csv << run << "," << position[0] << "," << position[1] << "," - << position[2]; + auto writeIntersection = [&](const Vector3& pos, const Surface& surface) { + csv << run << "," << pos[0] << "," << pos[1] << "," << pos[2]; csv << "," << surface.geometryId().volume(); csv << "," << surface.geometryId().boundary(); csv << "," << surface.geometryId().sensitive(); diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index cf7ceaea5e3..274986de71b 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -247,10 +247,8 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, } } - auto writeIntersection = [&](const Vector3& position, - const Surface& surface) { - csv << run << "," << position[0] << "," << position[1] << "," - << position[2]; + auto writeIntersection = [&](const Vector3& pos, const Surface& surface) { + csv << run << "," << pos[0] << "," << pos[1] << "," << pos[2]; csv << "," << surface.geometryId().volume(); csv << "," << surface.geometryId().boundary(); csv << "," << surface.geometryId().sensitive(); From 309714c4e57b410707fc519f4750bcbdcdc82b4e Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 18 Oct 2024 10:23:13 +0200 Subject: [PATCH 056/100] blueprint: Fix extent constructor call --- .../Core/Geometry/BlueprintNodeTests.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index 274986de71b..00d68df5a5f 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -596,10 +596,10 @@ BOOST_AUTO_TEST_CASE(LayerNodeDisk) { std::vector> surfaces = makeFan(2.5_mm); - RootBlueprintNode root{{.envelope{{ - .z = {2_mm, 2_mm}, - .r = {3_mm, 5_mm}, - }}}}; + RootBlueprintNode root{{.envelope = ExtentEnvelope{{ + .z = {2_mm, 2_mm}, + .r = {3_mm, 5_mm}, + }}}}; root.addLayer("Layer0", [&](auto& layer) { layer.setSurfaces(surfaces) @@ -643,10 +643,10 @@ BOOST_AUTO_TEST_CASE(LayerNodeCylinder) { std::vector> surfaces = makeBarrelLayer(base, detectorElements, 300_mm, 24, 8, 2.5_mm); - RootBlueprintNode root{{.envelope{{ - .z = {2_mm, 2_mm}, - .r = {3_mm, 5_mm}, - }}}}; + RootBlueprintNode root{{.envelope = ExtentEnvelope{{ + .z = {2_mm, 2_mm}, + .r = {3_mm, 5_mm}, + }}}}; root.addLayer("Layer0", [&](auto& layer) { layer.setSurfaces(surfaces) From 4b306580d866a6a3be3068eb368c8eabce4000c8 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 18 Oct 2024 11:25:45 +0200 Subject: [PATCH 057/100] blueprint: Cyl gap policy reg fix --- Core/src/Geometry/CylinderContainerBlueprintNode.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 649fd71ccbe..e4164ce4d42 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -167,10 +167,11 @@ void CylinderContainerBlueprintNode::finalize(const Options& options, ACTS_DEBUG(prefix() << "Registering " << m_gaps.size() << " gap volumes with parent"); for (auto& [shell, gap] : m_gaps) { - std::cout << "~> " << gap->volumeName() << std::endl; + auto* gapPtr = gap.get(); parent.addVolume(std::move(gap)); shell->applyToVolume(); - gap->setNavigationPolicy(policyFactory->build(gctx, *gap, logger)); + auto policy = policyFactory->build(gctx, *gapPtr, logger); + gapPtr->setNavigationPolicy(policyFactory->build(gctx, *gapPtr, logger)); } ACTS_DEBUG(prefix() << "Finalizing " << children().size() << " children"); From ab10d48844e5d7adc5533dda6510ae47203b988f Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 22 Oct 2024 17:21:55 +0200 Subject: [PATCH 058/100] blueprint: Update after nav API change --- Core/src/Geometry/BlueprintNode.cpp | 5 ++--- Examples/Python/src/Blueprint.cpp | 8 +++----- Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp | 7 +++---- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index c747b614171..f11f6ec60a0 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -13,7 +13,7 @@ #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Navigation/INavigationPolicy.hpp" -#include "Acts/Navigation/TryAllNavigationPolicies.hpp" +#include "Acts/Navigation/TryAllNavigationPolicy.hpp" #include @@ -58,8 +58,7 @@ void BlueprintNode::Options::validate() const { std::unique_ptr BlueprintNode::Options::makeDefaultNavigationPolicyFactory() { return NavigationPolicyFactory::make() - .add() - .add() + .add() .asUniquePtr(); } diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 89a13ac4c42..cc3b545576b 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -106,11 +106,9 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, for (std::size_t i = 0; i < 100; i++) { assert(currentVolume != nullptr); main = NavigationStream{}; - - currentVolume->updateNavigationState({.main = main, - .position = position, - .direction = direction, - .logger = logger()}); + AppendOnlyNavigationStream stream{main}; + currentVolume->initializeNavigationCandidates( + {.position = position, .direction = direction}, stream, logger()); ACTS_VERBOSE(main.candidates().size() << " candidates"); diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index 00d68df5a5f..b87bbf2130d 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -207,11 +207,10 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, for (std::size_t i = 0; i < 100; i++) { main = NavigationStream{}; + AppendOnlyNavigationStream stream{main}; - currentVolume->updateNavigationState({.main = main, - .position = position, - .direction = direction, - .logger = logger}); + currentVolume->initializeNavigationCandidates( + {.position = position, .direction = direction}, stream, logger); ACTS_VERBOSE(main.candidates().size() << " candidates"); From 6baa9c1800f331ae0eb9a1cbe1ad9c1d89fad48e Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 18 Nov 2024 17:03:59 +0100 Subject: [PATCH 059/100] blueprint: Rename RootBlueprintNode to Blueprint --- Core/include/Acts/Geometry/Blueprint.hpp | 42 ++++++++++++--- .../Acts/Geometry/RootBlueprintNode.hpp | 53 ------------------- .../{RootBlueprintNode.cpp => Blueprint.cpp} | 30 +++++------ Core/src/Geometry/CMakeLists.txt | 2 +- Examples/Python/src/Blueprint.cpp | 25 +++++---- Examples/Python/tests/test_blueprint.py | 2 +- Examples/Scripts/Python/blueprint.py | 2 +- .../Core/Geometry/BlueprintNodeTests.cpp | 40 +++++++------- 8 files changed, 84 insertions(+), 112 deletions(-) delete mode 100644 Core/include/Acts/Geometry/RootBlueprintNode.hpp rename Core/src/Geometry/{RootBlueprintNode.cpp => Blueprint.cpp} (80%) diff --git a/Core/include/Acts/Geometry/Blueprint.hpp b/Core/include/Acts/Geometry/Blueprint.hpp index 2492bb33738..12ade558d50 100644 --- a/Core/include/Acts/Geometry/Blueprint.hpp +++ b/Core/include/Acts/Geometry/Blueprint.hpp @@ -8,20 +8,46 @@ #pragma once -#include +#include "Acts/Geometry/BlueprintNode.hpp" +#include "Acts/Geometry/PortalShell.hpp" +#include "Acts/Geometry/TrackingGeometry.hpp" +#include "Acts/Geometry/TrackingVolume.hpp" namespace Acts { -class TrackingVolume; +class GeometryContext; -class Blueprint { - std::unique_ptr build(); +class Blueprint : public BlueprintNode { + public: + struct Config { + ExtentEnvelope envelope = ExtentEnvelope::Zero(); + GeometryIdentifierHook geometryIdentifierHook = {}; + }; - // void setStaticVolume(std::unique_ptr volume); + Blueprint(const Config& cfg); - // void setCylinderContainer( - // const std::function( - // std::unique_ptr cylinder)>& factory); + const std::string& name() const override; + + std::unique_ptr construct( + const Options& options, const GeometryContext& gctx, + const Logger& logger = Acts::getDummyLogger()); + + protected: + Volume& build(const Options& options, const GeometryContext& gctx, + const Logger& logger = Acts::getDummyLogger()) override; + + PortalShellBase& connect( + const Options& options, const GeometryContext& gctx, + const Logger& logger = Acts::getDummyLogger()) override; + + void finalize(const Options& options, const GeometryContext& gctx, + TrackingVolume& parent, + const Logger& logger = Acts::getDummyLogger()) override; + + void addToGraphviz(std::ostream& os) const override; + + private: + Config m_cfg; }; } // namespace Acts diff --git a/Core/include/Acts/Geometry/RootBlueprintNode.hpp b/Core/include/Acts/Geometry/RootBlueprintNode.hpp deleted file mode 100644 index 1f91af4812a..00000000000 --- a/Core/include/Acts/Geometry/RootBlueprintNode.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// This file is part of the ACTS project. -// -// Copyright (C) 2016 CERN for the benefit of the ACTS project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -#include "Acts/Geometry/BlueprintNode.hpp" -#include "Acts/Geometry/PortalShell.hpp" -#include "Acts/Geometry/TrackingGeometry.hpp" -#include "Acts/Geometry/TrackingVolume.hpp" - -namespace Acts { - -class GeometryContext; - -class RootBlueprintNode : public BlueprintNode { - public: - struct Config { - ExtentEnvelope envelope = ExtentEnvelope::Zero(); - GeometryIdentifierHook geometryIdentifierHook = {}; - }; - - RootBlueprintNode(const Config& cfg); - - const std::string& name() const override; - - std::unique_ptr construct( - const Options& options, const GeometryContext& gctx, - const Logger& logger = Acts::getDummyLogger()); - - protected: - Volume& build(const Options& options, const GeometryContext& gctx, - const Logger& logger = Acts::getDummyLogger()) override; - - PortalShellBase& connect( - const Options& options, const GeometryContext& gctx, - const Logger& logger = Acts::getDummyLogger()) override; - - void finalize(const Options& options, const GeometryContext& gctx, - TrackingVolume& parent, - const Logger& logger = Acts::getDummyLogger()) override; - - void addToGraphviz(std::ostream& os) const override; - - private: - Config m_cfg; -}; - -} // namespace Acts diff --git a/Core/src/Geometry/RootBlueprintNode.cpp b/Core/src/Geometry/Blueprint.cpp similarity index 80% rename from Core/src/Geometry/RootBlueprintNode.cpp rename to Core/src/Geometry/Blueprint.cpp index 83e6cefd40e..a7ed2347db4 100644 --- a/Core/src/Geometry/RootBlueprintNode.cpp +++ b/Core/src/Geometry/Blueprint.cpp @@ -6,7 +6,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -#include "Acts/Geometry/RootBlueprintNode.hpp" +#include "Acts/Geometry/Blueprint.hpp" #include "Acts/Geometry/CuboidVolumeBounds.hpp" #include "Acts/Geometry/CylinderVolumeBounds.hpp" @@ -18,33 +18,33 @@ namespace Acts { -RootBlueprintNode::RootBlueprintNode(const Config &cfg) : m_cfg(cfg) {} +Blueprint::Blueprint(const Config &cfg) : m_cfg(cfg) {} -const std::string &RootBlueprintNode::name() const { +const std::string &Blueprint::name() const { static const std::string root = "root"; return root; } -Volume &RootBlueprintNode::build(const Options & /*options*/, - const GeometryContext & /*gctx*/, - const Logger & /*logger*/) { +Volume &Blueprint::build(const Options & /*options*/, + const GeometryContext & /*gctx*/, + const Logger & /*logger*/) { throw std::logic_error("Root node cannot be built"); } -PortalShellBase &RootBlueprintNode::connect(const Options & /*options*/, - const GeometryContext & /*gctx*/, - const Logger & /*logger*/) { +PortalShellBase &Blueprint::connect(const Options & /*options*/, + const GeometryContext & /*gctx*/, + const Logger & /*logger*/) { throw std::logic_error("Root node cannot be connected"); } -void RootBlueprintNode::finalize(const Options & /*options*/, - const GeometryContext & /*gctx*/, - TrackingVolume & /*parent*/, - const Logger & /*logger*/) { +void Blueprint::finalize(const Options & /*options*/, + const GeometryContext & /*gctx*/, + TrackingVolume & /*parent*/, + const Logger & /*logger*/) { throw std::logic_error("Root node cannot be finalized"); } -void RootBlueprintNode::addToGraphviz(std::ostream &os) const { +void Blueprint::addToGraphviz(std::ostream &os) const { GraphViz::Node node{ .id = name(), .label = "World", .shape = GraphViz::Shape::House}; @@ -52,7 +52,7 @@ void RootBlueprintNode::addToGraphviz(std::ostream &os) const { BlueprintNode::addToGraphviz(os); } -std::unique_ptr RootBlueprintNode::construct( +std::unique_ptr Blueprint::construct( const Options &options, const GeometryContext &gctx, const Logger &logger) { using enum BinningValue; diff --git a/Core/src/Geometry/CMakeLists.txt b/Core/src/Geometry/CMakeLists.txt index 9a7ebc2a9a3..6fcf65eb46e 100644 --- a/Core/src/Geometry/CMakeLists.txt +++ b/Core/src/Geometry/CMakeLists.txt @@ -44,7 +44,7 @@ target_sources( PortalError.cpp PortalShell.cpp BlueprintNode.cpp - RootBlueprintNode.cpp + Blueprint.cpp CylinderContainerBlueprintNode.cpp StaticBlueprintNode.cpp LayerBlueprintNode.cpp diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index cc3b545576b..07b94c009dd 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -6,13 +6,14 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. +#include "Acts/Geometry/Blueprint.hpp" + #include "Acts/Definitions/Units.hpp" #include "Acts/Geometry/BlueprintNode.hpp" #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/CylinderVolumeStack.hpp" #include "Acts/Geometry/LayerBlueprintNode.hpp" #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" -#include "Acts/Geometry/RootBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Navigation/NavigationStream.hpp" #include "Acts/Plugins/Python/Utilities.hpp" @@ -63,7 +64,7 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, Vector3 position = Vector3::Zero(); double theta = thetaDist(rnd); - double phi = 2 * M_PI * dist(rnd); + double phi = 2 * std::numbers::pi * dist(rnd); Vector3 direction; direction[0] = std::sin(theta) * std::cos(phi); @@ -283,28 +284,26 @@ void addBlueprint(Context& ctx) { }); { - auto n = - py::class_>(m, "RootBlueprintNode"); + auto n = py::class_>( + m, "Blueprint"); - n.def(py::init()) - .def_property_readonly("name", &RootBlueprintNode::name) + n.def(py::init()) + .def_property_readonly("name", &Blueprint::name) // Return value needs to be shared pointer because python otherwise // can't manage the lifetime .def( "construct", - [](RootBlueprintNode& self, - const RootBlueprintNode::Options& options, + [](Blueprint& self, const Blueprint::Options& options, const GeometryContext& gctx, Logging::Level level) -> std::shared_ptr { - return self.construct( - options, gctx, *getDefaultLogger("RootBlueprintNode", level)); + return self.construct(options, gctx, + *getDefaultLogger("Blueprint", level)); }, py::arg("options"), py::arg("gctx"), py::arg("level") = Logging::INFO); - auto c = py::class_(n, "Config").def(py::init()); - ACTS_PYTHON_STRUCT_BEGIN(c, RootBlueprintNode::Config); + auto c = py::class_(n, "Config").def(py::init()); + ACTS_PYTHON_STRUCT_BEGIN(c, Blueprint::Config); ACTS_PYTHON_MEMBER(envelope); ACTS_PYTHON_MEMBER(geometryIdentifierHook); ACTS_PYTHON_STRUCT_END(); diff --git a/Examples/Python/tests/test_blueprint.py b/Examples/Python/tests/test_blueprint.py index efeb3eedd63..d79f60f03cd 100644 --- a/Examples/Python/tests/test_blueprint.py +++ b/Examples/Python/tests/test_blueprint.py @@ -22,7 +22,7 @@ def write(root: acts.BlueprintNode, stage: int): base = acts.Transform3.Identity() - root = acts.RootBlueprintNode(envelope=acts.ExtentEnvelope(r=[10 * mm, 10 * mm])) + root = acts.Blueprint(envelope=acts.ExtentEnvelope(r=[10 * mm, 10 * mm])) barrel = root.addCylinderContainer("Barrel", direction=bv.binR) diff --git a/Examples/Scripts/Python/blueprint.py b/Examples/Scripts/Python/blueprint.py index 6f4eb829bb9..3d516cd9b91 100755 --- a/Examples/Scripts/Python/blueprint.py +++ b/Examples/Scripts/Python/blueprint.py @@ -7,7 +7,7 @@ mm = acts.UnitConstants.mm degree = acts.UnitConstants.degree -root = acts.RootBlueprintNode(envelope=acts.ExtentEnvelope(r=[10 * mm, 10 * mm])) +root = acts.Blueprint(envelope=acts.ExtentEnvelope(r=[10 * mm, 10 * mm])) pixel = root.addCylinderContainer(direction=acts.BinningValue.binZ, name="Pixel") diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp index b87bbf2130d..09497c8617a 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp @@ -14,12 +14,12 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Definitions/Units.hpp" #include "Acts/Detector/ProtoBinning.hpp" +#include "Acts/Geometry/Blueprint.hpp" #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/CylinderVolumeBounds.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/LayerBlueprintNode.hpp" #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" -#include "Acts/Geometry/RootBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Geometry/TrackingVolume.hpp" #include "Acts/Navigation/INavigationPolicy.hpp" @@ -48,7 +48,7 @@ inline std::vector> makeFanLayer( double r = 300_mm, std::size_t nSensors = 8, double thickness = 0) { auto recBounds = std::make_shared(40_mm, 60_mm); - double deltaPhi = 2 * M_PI / nSensors; + double deltaPhi = 2 * std::numbers::pi / nSensors; std::vector> surfaces; for (std::size_t i = 0; i < nSensors; i++) { // Create a fan of sensors @@ -77,7 +77,7 @@ inline std::vector> makeBarrelLayer( double thickness = 0, double hlPhi = 40_mm, double hlZ = 60_mm) { auto recBounds = std::make_shared(hlPhi, hlZ); - double deltaPhi = 2 * M_PI / nStaves; + double deltaPhi = 2 * std::numbers::pi / nStaves; std::vector> surfaces; for (std::size_t istave = 0; istave < nStaves; istave++) { @@ -106,9 +106,9 @@ BOOST_AUTO_TEST_SUITE(Geometry); BOOST_AUTO_TEST_SUITE(BlueprintNodeTest); BOOST_AUTO_TEST_CASE(StaticBlueprintNodeConstruction) { - RootBlueprintNode::Config cfg; + Blueprint::Config cfg; cfg.envelope[BinningValue::binZ] = {20_mm, 2_mm}; - RootBlueprintNode root{cfg}; + Blueprint root{cfg}; ActsScalar hlZ = 30_mm; auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); @@ -160,10 +160,10 @@ BOOST_AUTO_TEST_CASE(CylinderContainerNode) { ActsScalar hlZ = 30_mm; auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); - RootBlueprintNode::Config cfg; + Blueprint::Config cfg; cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; cfg.envelope[BinningValue::binR] = {0_mm, 20_mm}; - auto root = std::make_unique(cfg); + auto root = std::make_unique(cfg); auto& cyl = root->addCylinderContainer("Container", BinningValue::binZ); @@ -361,10 +361,10 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { return makeFanLayer(layerBase, detectorElements, r, nSensors, thickness); }; - RootBlueprintNode::Config cfg; + Blueprint::Config cfg; cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; cfg.envelope[BinningValue::binR] = {0_mm, 20_mm}; - auto root = std::make_unique(cfg); + auto root = std::make_unique(cfg); root->addMaterial("GlobalMaterial", [&](MaterialDesignatorBlueprintNode& mat) { @@ -498,7 +498,7 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { for (std::size_t i = 0; i < 5000; i++) { double theta = thetaDist(rnd); - double phi = 2 * M_PI * dist(rnd); + double phi = 2 * std::numbers::pi * dist(rnd); Vector3 direction; direction[0] = std::sin(theta) * std::cos(phi); @@ -516,10 +516,10 @@ BOOST_AUTO_TEST_CASE(NodeApiTestConfined) { // Transform3 base{AngleAxis3{30_degree, Vector3{1, 0, 0}}}; Transform3 base{Transform3::Identity()}; - RootBlueprintNode::Config cfg; + Blueprint::Config cfg; cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; cfg.envelope[BinningValue::binR] = {0_mm, 20_mm}; - auto root = std::make_unique(cfg); + auto root = std::make_unique(cfg); root->addCylinderContainer("Detector", BinningValue::binR, [&](auto& det) { det.addStaticVolume( @@ -595,10 +595,10 @@ BOOST_AUTO_TEST_CASE(LayerNodeDisk) { std::vector> surfaces = makeFan(2.5_mm); - RootBlueprintNode root{{.envelope = ExtentEnvelope{{ - .z = {2_mm, 2_mm}, - .r = {3_mm, 5_mm}, - }}}}; + Blueprint root{{.envelope = ExtentEnvelope{{ + .z = {2_mm, 2_mm}, + .r = {3_mm, 5_mm}, + }}}}; root.addLayer("Layer0", [&](auto& layer) { layer.setSurfaces(surfaces) @@ -642,10 +642,10 @@ BOOST_AUTO_TEST_CASE(LayerNodeCylinder) { std::vector> surfaces = makeBarrelLayer(base, detectorElements, 300_mm, 24, 8, 2.5_mm); - RootBlueprintNode root{{.envelope = ExtentEnvelope{{ - .z = {2_mm, 2_mm}, - .r = {3_mm, 5_mm}, - }}}}; + Blueprint root{{.envelope = ExtentEnvelope{{ + .z = {2_mm, 2_mm}, + .r = {3_mm, 5_mm}, + }}}}; root.addLayer("Layer0", [&](auto& layer) { layer.setSurfaces(surfaces) From 163600130444c0326aa193c324d6fd432ce73ab8 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 18 Nov 2024 17:07:31 +0100 Subject: [PATCH 060/100] blueprint: Blueprint inherits privately from BlueprintNode --- Core/include/Acts/Geometry/Blueprint.hpp | 9 ++++++++- Examples/Python/src/Blueprint.cpp | 3 +-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Core/include/Acts/Geometry/Blueprint.hpp b/Core/include/Acts/Geometry/Blueprint.hpp index 12ade558d50..0752f069fea 100644 --- a/Core/include/Acts/Geometry/Blueprint.hpp +++ b/Core/include/Acts/Geometry/Blueprint.hpp @@ -17,8 +17,15 @@ namespace Acts { class GeometryContext; -class Blueprint : public BlueprintNode { +class Blueprint : private BlueprintNode { public: + using BlueprintNode::addChild; + using BlueprintNode::addCylinderContainer; + using BlueprintNode::addLayer; + using BlueprintNode::addMaterial; + using BlueprintNode::graphViz; + using BlueprintNode::Options; + struct Config { ExtentEnvelope envelope = ExtentEnvelope::Zero(); GeometryIdentifierHook geometryIdentifierHook = {}; diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 07b94c009dd..4bb29fb647a 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -284,8 +284,7 @@ void addBlueprint(Context& ctx) { }); { - auto n = py::class_>( - m, "Blueprint"); + auto n = py::class_>(m, "Blueprint"); n.def(py::init()) .def_property_readonly("name", &Blueprint::name) From fa2f85880f2028acde3549370af30f70d0d24aa3 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 6 Nov 2024 15:42:05 +0100 Subject: [PATCH 061/100] blueprint: Update after nav API change --- Examples/Python/src/Blueprint.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 4bb29fb647a..1294aa8461e 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -107,9 +107,10 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, for (std::size_t i = 0; i < 100; i++) { assert(currentVolume != nullptr); main = NavigationStream{}; - AppendOnlyNavigationStream stream{main}; + + AppendOnlyNavigationStream navStream{main}; currentVolume->initializeNavigationCandidates( - {.position = position, .direction = direction}, stream, logger()); + {.position = position, .direction = direction}, navStream, logger()); ACTS_VERBOSE(main.candidates().size() << " candidates"); From a4a73a732bc81573ffba9b8d243cbad206e1f9a3 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 27 Nov 2024 17:03:11 +0100 Subject: [PATCH 062/100] rename gen2 blueprint test --- Tests/UnitTests/Core/Detector/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/UnitTests/Core/Detector/CMakeLists.txt b/Tests/UnitTests/Core/Detector/CMakeLists.txt index eff298adb84..0c51456d7e4 100644 --- a/Tests/UnitTests/Core/Detector/CMakeLists.txt +++ b/Tests/UnitTests/Core/Detector/CMakeLists.txt @@ -1,4 +1,4 @@ -add_unittest(Blueprint BlueprintTests.cpp) +add_unittest(Gen2Blueprint BlueprintTests.cpp) add_unittest(BlueprintHelper BlueprintHelperTests.cpp) add_unittest(CylindricalContainerBuilder CylindricalContainerBuilderTests.cpp) add_unittest(CylindricalDetectorFromBlueprint CylindricalDetectorFromBlueprintTests.cpp) From b10c97720a14fa84670f703643f3fecaeaa55744 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 27 Nov 2024 17:03:54 +0100 Subject: [PATCH 063/100] rename existing test to API test, remove some lower level tests --- ...intNodeTests.cpp => BlueprintApiTests.cpp} | 284 +----------------- Tests/UnitTests/Core/Geometry/CMakeLists.txt | 2 +- 2 files changed, 4 insertions(+), 282 deletions(-) rename Tests/UnitTests/Core/Geometry/{BlueprintNodeTests.cpp => BlueprintApiTests.cpp} (62%) diff --git a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp similarity index 62% rename from Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp rename to Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp index 09497c8617a..513998e62c9 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintNodeTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp @@ -17,10 +17,11 @@ #include "Acts/Geometry/Blueprint.hpp" #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/CylinderVolumeStack.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/LayerBlueprintNode.hpp" #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" -#include "Acts/Geometry/StaticBlueprintNode.hpp" +#include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Geometry/TrackingVolume.hpp" #include "Acts/Navigation/INavigationPolicy.hpp" #include "Acts/Navigation/NavigationStream.hpp" @@ -103,81 +104,7 @@ inline std::vector> makeBarrelLayer( BOOST_AUTO_TEST_SUITE(Geometry); -BOOST_AUTO_TEST_SUITE(BlueprintNodeTest); - -BOOST_AUTO_TEST_CASE(StaticBlueprintNodeConstruction) { - Blueprint::Config cfg; - cfg.envelope[BinningValue::binZ] = {20_mm, 2_mm}; - Blueprint root{cfg}; - - ActsScalar hlZ = 30_mm; - auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); - auto cyl = std::make_unique(Transform3::Identity(), cylBounds, - "root"); - - const auto* cylPtr = cyl.get(); - - auto node = std::make_unique(std::move(cyl)); - - BOOST_CHECK_EQUAL(node->name(), "root"); - - BOOST_CHECK_EQUAL(&node->build({}, gctx), cylPtr); - - ObjVisualization3D vis; - // Add some children - ActsScalar z0 = -200_mm; - for (std::size_t i = 0; i < 10; i++) { - auto childCyl = std::make_unique( - Transform3::Identity() * - Translation3{Vector3{0, 0, z0 + i * 2 * hlZ * 1.2}}, - cylBounds, "child" + std::to_string(i)); - - GeometryView3D::drawVolume(vis, *childCyl, gctx); - - node->addChild(std::make_unique(std::move(childCyl))); - } - - BOOST_CHECK_EQUAL(node->children().size(), 10); - - root.addChild(std::move(node)); - - std::ofstream ofs{"static.obj"}; - vis.write(ofs); - - auto tGeometry = root.construct({}, gctx, *logger); - - BOOST_REQUIRE(tGeometry); - - BOOST_CHECK_EQUAL(tGeometry->highestTrackingVolume()->volumes().size(), 1); - std::size_t nVolumes = 0; - tGeometry->visitVolumes( - [&](const TrackingVolume* /*volume*/) { nVolumes++; }); - - BOOST_CHECK_EQUAL(nVolumes, 12); -} - -BOOST_AUTO_TEST_CASE(CylinderContainerNode) { - ActsScalar hlZ = 30_mm; - auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); - - Blueprint::Config cfg; - cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; - cfg.envelope[BinningValue::binR] = {0_mm, 20_mm}; - auto root = std::make_unique(cfg); - - auto& cyl = root->addCylinderContainer("Container", BinningValue::binZ); - - ActsScalar z0 = -200_mm; - for (std::size_t i = 0; i < 10; i++) { - auto childCyl = std::make_unique( - Transform3::Identity() * - Translation3{Vector3{0, 0, z0 + i * 2 * hlZ * 1.2}}, - cylBounds, "child" + std::to_string(i)); - cyl.addStaticVolume(std::move(childCyl)); - } - - root->construct({}, gctx, *logger); -} +BOOST_AUTO_TEST_SUITE(BlueprintApiTest); void pseudoNavigation(const TrackingGeometry& trackingGeometry, Vector3 position, const Vector3& direction, @@ -316,41 +243,6 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, } } -void portalSamples(const TrackingGeometry& trackingGeometry, Vector3 position, - const Vector3& direction, std::ostream& csv, - std::size_t run) { - std::set visitedSurfaces; - - trackingGeometry.visitVolumes([&](const TrackingVolume* volume) { - for (const auto& portal : volume->portals()) { - if (visitedSurfaces.contains(&portal.surface())) { - continue; - } - visitedSurfaces.insert(&portal.surface()); - - auto multiIntersection = portal.surface().intersect( - gctx, position, direction, BoundaryTolerance::None()); - - for (const auto& intersection : multiIntersection.split()) { - if (intersection.isValid()) { - Vector3 newPosition = intersection.position(); - csv << run << "," << position[0] << "," << position[1] << "," - << position[2]; - csv << "," << volume->geometryId().volume(); - csv << "," << volume->geometryId().boundary(); - csv << std::endl; - csv << run << "," << newPosition[0] << "," << newPosition[1] << "," - << newPosition[2]; - csv << "," << portal.surface().geometryId().volume(); - csv << "," << portal.surface().geometryId().boundary(); - csv << std::endl; - position = newPosition; - } - } - } - }); -} - BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { // Transform3 base{AngleAxis3{30_degree, Vector3{1, 0, 0}}}; Transform3 base{Transform3::Identity()}; @@ -507,179 +399,9 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { pseudoNavigation(*trackingGeometry, position, direction, csv, i, 2, *logger->clone(std::nullopt, Logging::DEBUG)); - - // portalSamples(*trackingGeometry, position, direction, csv, i); } } -BOOST_AUTO_TEST_CASE(NodeApiTestConfined) { - // Transform3 base{AngleAxis3{30_degree, Vector3{1, 0, 0}}}; - Transform3 base{Transform3::Identity()}; - - Blueprint::Config cfg; - cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; - cfg.envelope[BinningValue::binR] = {0_mm, 20_mm}; - auto root = std::make_unique(cfg); - - root->addCylinderContainer("Detector", BinningValue::binR, [&](auto& det) { - det.addStaticVolume( - base, std::make_shared(50_mm, 400_mm, 1000_mm), - "PixelWrapper", [&](auto& wrap) { - ActsScalar rMin = 100_mm; - ActsScalar rMax = 350_mm; - ActsScalar hlZ = 100_mm; - - wrap.addStaticVolume( - base * Translation3{Vector3{0, 0, -600_mm}}, - std::make_shared(rMin, rMax, hlZ), - "PixelNeg1"); - - wrap.addStaticVolume( - base * Translation3{Vector3{0, 0, -200_mm}}, - std::make_shared(rMin, rMax, hlZ), - "PixelNeg2"); - - wrap.addStaticVolume( - base * Translation3{Vector3{0, 0, 200_mm}}, - std::make_shared(rMin, rMax, hlZ), - "PixelPos1"); - - wrap.addStaticVolume( - base * Translation3{Vector3{0, 0, 600_mm}}, - std::make_shared(rMin, rMax, hlZ), - "PixelPos2"); - }); - - det.addStaticVolume( - base, std::make_shared(0_mm, 23_mm, 1000_mm), - "BeamPipe"); - }); - - std::ofstream dot{"api_test_confined.dot"}; - root->graphViz(dot); - - auto trackingGeometry = root->construct({}, gctx, *logger); - - trackingGeometry->visitVolumes([&](const TrackingVolume* volume) { - std::cout << volume->volumeName() << std::endl; - std::cout << " -> id: " << volume->geometryId() << std::endl; - std::cout << " -> " << volume->portals().size() << " portals" << std::endl; - }); - - ObjVisualization3D vis; - - trackingGeometry->visualize(vis, gctx, {}, {}); - - vis.write("api_test_confined.obj"); - - const auto* wrapper = - trackingGeometry->findVolume(GeometryIdentifier{}.setVolume(2)); - BOOST_REQUIRE_NE(wrapper, nullptr); - - std::cout << wrapper->volumeName() << std::endl; - - BOOST_CHECK_EQUAL(wrapper->portals().size(), 20); - BOOST_CHECK_EQUAL(wrapper->volumes().size(), 4); -} - -BOOST_AUTO_TEST_CASE(LayerNodeDisk) { - double yrot = 45_degree; - Transform3 base = Transform3::Identity() * AngleAxis3{yrot, Vector3::UnitY()}; - - std::vector> detectorElements; - - auto makeFan = [&](double thickness) { - detectorElements.clear(); - return makeFanLayer(base, detectorElements, 200_mm, 10, thickness); - }; - - std::vector> surfaces = makeFan(2.5_mm); - - Blueprint root{{.envelope = ExtentEnvelope{{ - .z = {2_mm, 2_mm}, - .r = {3_mm, 5_mm}, - }}}}; - - root.addLayer("Layer0", [&](auto& layer) { - layer.setSurfaces(surfaces) - .setLayerType(LayerBlueprintNode::LayerType::Disc) - .setEnvelope(ExtentEnvelope{{ - .z = {0.1_mm, 0.1_mm}, - .r = {1_mm, 1_mm}, - }}) - .setTransform(base); - }); - - std::ofstream dot{"layer_node_disk.dot"}; - root.graphViz(dot); - - auto trackingGeometry = - root.construct({}, gctx, *logger->clone(std::nullopt, Logging::VERBOSE)); - - ObjVisualization3D vis; - - trackingGeometry->visualize(vis, gctx, {}, {}); - - vis.write("layer_node_disk.obj"); - - std::size_t nSurfaces = 0; - - trackingGeometry->visitSurfaces([&](const Surface* surface) { - if (surface->associatedDetectorElement() != nullptr) { - nSurfaces++; - } - }); - - BOOST_CHECK_EQUAL(nSurfaces, surfaces.size()); -} - -BOOST_AUTO_TEST_CASE(LayerNodeCylinder) { - double yrot = 0_degree; - Transform3 base = Transform3::Identity() * AngleAxis3{yrot, Vector3::UnitY()}; - - std::vector> detectorElements; - - std::vector> surfaces = - makeBarrelLayer(base, detectorElements, 300_mm, 24, 8, 2.5_mm); - - Blueprint root{{.envelope = ExtentEnvelope{{ - .z = {2_mm, 2_mm}, - .r = {3_mm, 5_mm}, - }}}}; - - root.addLayer("Layer0", [&](auto& layer) { - layer.setSurfaces(surfaces) - .setLayerType(LayerBlueprintNode::LayerType::Cylinder) - .setEnvelope(ExtentEnvelope{{ - .z = {10_mm, 10_mm}, - .r = {20_mm, 10_mm}, - }}) - .setTransform(base); - }); - - std::ofstream dot{"layer_node_cyl.dot"}; - root.graphViz(dot); - - auto trackingGeometry = - root.construct({}, gctx, *logger->clone(std::nullopt, Logging::VERBOSE)); - - ObjVisualization3D vis; - - trackingGeometry->visualize(vis, gctx, {}, {}); - - vis.write("layer_node_cyl.obj"); - - std::size_t nSurfaces = 0; - - trackingGeometry->visitSurfaces([&](const Surface* surface) { - if (surface->associatedDetectorElement() != nullptr) { - nSurfaces++; - } - }); - - BOOST_CHECK_EQUAL(nSurfaces, surfaces.size()); -} - BOOST_AUTO_TEST_SUITE_END(); BOOST_AUTO_TEST_SUITE_END(); diff --git a/Tests/UnitTests/Core/Geometry/CMakeLists.txt b/Tests/UnitTests/Core/Geometry/CMakeLists.txt index 3c525768661..39d7abc3740 100644 --- a/Tests/UnitTests/Core/Geometry/CMakeLists.txt +++ b/Tests/UnitTests/Core/Geometry/CMakeLists.txt @@ -35,4 +35,4 @@ add_unittest(CylinderVolumeStack CylinderVolumeStackTests.cpp) add_unittest(PortalLink PortalLinkTests.cpp) add_unittest(Portal PortalTests.cpp) add_unittest(PortalShell PortalShellTests.cpp) -add_unittest(BlueprintNode BlueprintNodeTests.cpp) +add_unittest(BlueprintApi BlueprintApiTests.cpp) From a7e5dc083aae5b74fed1a5b8c710a934b2697cf9 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 27 Nov 2024 17:06:08 +0100 Subject: [PATCH 064/100] fix material node error check, blueprint api fix --- Core/include/Acts/Geometry/Blueprint.hpp | 3 +++ Core/src/Geometry/Blueprint.cpp | 14 +++++++++++++- .../Geometry/MaterialDesignatorBlueprintNode.cpp | 10 +++++----- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Core/include/Acts/Geometry/Blueprint.hpp b/Core/include/Acts/Geometry/Blueprint.hpp index 0752f069fea..b98f642bdf4 100644 --- a/Core/include/Acts/Geometry/Blueprint.hpp +++ b/Core/include/Acts/Geometry/Blueprint.hpp @@ -23,7 +23,10 @@ class Blueprint : private BlueprintNode { using BlueprintNode::addCylinderContainer; using BlueprintNode::addLayer; using BlueprintNode::addMaterial; + using BlueprintNode::addStaticVolume; + using BlueprintNode::children; using BlueprintNode::graphViz; + using BlueprintNode::Options; struct Config { diff --git a/Core/src/Geometry/Blueprint.cpp b/Core/src/Geometry/Blueprint.cpp index a7ed2347db4..56de14c0f5d 100644 --- a/Core/src/Geometry/Blueprint.cpp +++ b/Core/src/Geometry/Blueprint.cpp @@ -94,6 +94,9 @@ std::unique_ptr Blueprint::construct( if (zEnv[0] != zEnv[1]) { ACTS_ERROR( prefix() << "Root node cylinder envelope for z must be symmetric"); + throw std::logic_error( + "Root node cylinder envelope for z must be " + "symmetric"); } const auto &rEnv = m_cfg.envelope[binR]; @@ -133,9 +136,18 @@ std::unique_ptr Blueprint::construct( child.finalize(options, gctx, *world, logger); - // @TODO: Handle material decorator, geo id hook // @TODO: Maybe add a name uniqueness check + std::set names; + + world->visitVolumes([&](const auto *volume) { + if (names.contains(volume->volumeName())) { + ACTS_ERROR(prefix() << "Duplicate volume name: " << volume->volumeName()); + throw std::logic_error("Duplicate volume name"); + } + names.insert(volume->volumeName()); + }); + return std::make_unique( std::move(world), nullptr, m_cfg.geometryIdentifierHook, logger); } diff --git a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp index ed6eb58fb66..b0db3001ad7 100644 --- a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp +++ b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp @@ -84,14 +84,14 @@ PortalShellBase& MaterialDesignatorBlueprintNode::connect( } if (face == PositiveDisc || face == NegativeDisc) { - if (loc0.binValue != BinningValue::binPhi) { - ACTS_ERROR(prefix() << "Binning is not in Phi"); - throw std::runtime_error("Binning is not in Phi"); - } - if (loc1.binValue != BinningValue::binR) { + if (loc0.binValue != BinningValue::binR) { ACTS_ERROR(prefix() << "Binning is not in R"); throw std::runtime_error("Binning is not in R"); } + if (loc1.binValue != BinningValue::binPhi) { + ACTS_ERROR(prefix() << "Binning is not in Phi"); + throw std::runtime_error("Binning is not in Phi"); + } } Experimental::BinningDescription desc{.binning = {loc0, loc1}}; From 1a81501daa68b20b14f59116eadc127448fd5307 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 27 Nov 2024 17:06:51 +0100 Subject: [PATCH 065/100] add better unit test for individual node types --- .../Core/Geometry/BlueprintTests.cpp | 453 ++++++++++++++++++ Tests/UnitTests/Core/Geometry/CMakeLists.txt | 1 + 2 files changed, 454 insertions(+) create mode 100644 Tests/UnitTests/Core/Geometry/BlueprintTests.cpp diff --git a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp new file mode 100644 index 00000000000..b339167239d --- /dev/null +++ b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp @@ -0,0 +1,453 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include +#include +#include +#include + +#include "Acts/Definitions/Units.hpp" +#include "Acts/Geometry/Blueprint.hpp" +#include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" +#include "Acts/Geometry/CylinderVolumeBounds.hpp" +#include "Acts/Geometry/CylinderVolumeStack.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Geometry/LayerBlueprintNode.hpp" +#include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" +#include "Acts/Geometry/StaticBlueprintNode.hpp" +#include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Material/BinnedSurfaceMaterial.hpp" +#include "Acts/Material/ProtoSurfaceMaterial.hpp" +#include "Acts/Surfaces/RectangleBounds.hpp" +#include "Acts/Tests/CommonHelpers/DetectorElementStub.hpp" +#include "Acts/Utilities/BinningType.hpp" +#include "Acts/Utilities/Logger.hpp" + +#include +#include +#include + +using namespace Acts::UnitLiterals; + +namespace Acts::Test { + +auto logger = Acts::getDefaultLogger("UnitTests", Acts::Logging::INFO); + +GeometryContext gctx; + +namespace { + +auto nameLookup(const TrackingGeometry& geo) { + return [&](const std::string& name) -> const TrackingVolume& { + const TrackingVolume* volume = nullptr; + + geo.visitVolumes([&](const TrackingVolume* v) { + if (v->volumeName() == name) { + volume = v; + } + }); + + if (volume == nullptr) { + throw std::runtime_error("Volume not found: " + name); + } + return *volume; + }; +} + +std::size_t countVolumes(const TrackingGeometry& geo) { + std::size_t nVolumes = 0; + geo.visitVolumes([&](const TrackingVolume* /*volume*/) { nVolumes++; }); + return nVolumes; +} + +} // namespace + +BOOST_AUTO_TEST_SUITE(Geometry); + +BOOST_AUTO_TEST_SUITE(BlueprintNodeTest); + +BOOST_AUTO_TEST_CASE(InvalidRoot) { + Blueprint::Config cfg; + Blueprint root{cfg}; + BOOST_CHECK_THROW(root.construct({}, gctx, *logger), std::logic_error); + + // More than one child is also invalid + auto cylBounds = std::make_shared(10_mm, 20_mm, 100_mm); + root.addChild( + std::make_unique(std::make_unique( + Transform3::Identity(), cylBounds, "child1"))); + root.addChild( + std::make_unique(std::make_unique( + Transform3::Identity(), cylBounds, "child2"))); + + BOOST_CHECK_THROW(root.construct({}, gctx, *logger), std::logic_error); +} + +BOOST_AUTO_TEST_CASE(Static) { + Blueprint::Config cfg; + cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; + cfg.envelope[BinningValue::binR] = {1_mm, 2_mm}; + Blueprint root{cfg}; + + ActsScalar hlZ = 30_mm; + auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); + auto cyl = std::make_unique(Transform3::Identity(), cylBounds, + "child"); + + root.addStaticVolume(std::move(cyl)); + + BOOST_CHECK_EQUAL(root.children().size(), 1); + + auto tGeometry = root.construct({}, gctx, *logger); + + BOOST_REQUIRE(tGeometry); + + BOOST_CHECK_EQUAL(tGeometry->highestTrackingVolume()->volumes().size(), 1); + + BOOST_CHECK_EQUAL(countVolumes(*tGeometry), 2); + + auto lookup = nameLookup(*tGeometry); + auto actCyl = + dynamic_cast(lookup("child").volumeBounds()); + // Size as given + BOOST_CHECK_EQUAL(actCyl.get(CylinderVolumeBounds::eMinR), 10_mm); + BOOST_CHECK_EQUAL(actCyl.get(CylinderVolumeBounds::eMaxR), 20_mm); + BOOST_CHECK_EQUAL(actCyl.get(CylinderVolumeBounds::eHalfLengthZ), hlZ); + + auto worldCyl = + dynamic_cast(lookup("World").volumeBounds()); + BOOST_CHECK_EQUAL(worldCyl.get(CylinderVolumeBounds::eMinR), 9_mm); + BOOST_CHECK_EQUAL(worldCyl.get(CylinderVolumeBounds::eMaxR), 22_mm); + BOOST_CHECK_EQUAL(worldCyl.get(CylinderVolumeBounds::eHalfLengthZ), + hlZ + 20_mm); + + BOOST_CHECK_EQUAL(lookup("World").portals().size(), 8); +} + +BOOST_AUTO_TEST_CASE(CylinderContainer) { + Blueprint::Config cfg; + cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; + cfg.envelope[BinningValue::binR] = {2_mm, 20_mm}; + auto root = std::make_unique(cfg); + + auto& cyl = root->addCylinderContainer("Container", BinningValue::binZ); + cyl.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap); + + ActsScalar z0 = -200_mm; + ActsScalar hlZ = 30_mm; + auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); + for (std::size_t i = 0; i < 3; i++) { + auto childCyl = std::make_unique( + Transform3::Identity() * + Translation3{Vector3{0, 0, z0 + i * 2 * hlZ * 1.2}}, + cylBounds, "child" + std::to_string(i)); + cyl.addStaticVolume(std::move(childCyl)); + } + + auto tGeometry = root->construct({}, gctx, *logger); + + // 4 real volumes + 2 gaps + BOOST_CHECK_EQUAL(countVolumes(*tGeometry), 6); + + auto lookup = nameLookup(*tGeometry); + auto worldCyl = + dynamic_cast(lookup("World").volumeBounds()); + BOOST_CHECK_EQUAL(worldCyl.get(CylinderVolumeBounds::eMinR), 8_mm); + BOOST_CHECK_EQUAL(worldCyl.get(CylinderVolumeBounds::eMaxR), 40_mm); + BOOST_CHECK_EQUAL(worldCyl.get(CylinderVolumeBounds::eHalfLengthZ), 122_mm); + + BOOST_CHECK_EQUAL(lookup("World").portals().size(), 8); + + for (std::size_t i = 0; i < 3; i++) { + auto actCyl = dynamic_cast( + lookup("child" + std::to_string(i)).volumeBounds()); + BOOST_CHECK_EQUAL(actCyl.get(CylinderVolumeBounds::eMinR), 10_mm); + BOOST_CHECK_EQUAL(actCyl.get(CylinderVolumeBounds::eMaxR), 20_mm); + BOOST_CHECK_EQUAL(actCyl.get(CylinderVolumeBounds::eHalfLengthZ), hlZ); + } + + for (std::size_t i = 0; i < 2; i++) { + auto gapCyl = dynamic_cast( + lookup("Container::Gap" + std::to_string(i + 1)).volumeBounds()); + BOOST_CHECK_EQUAL(gapCyl.get(CylinderVolumeBounds::eMinR), 10_mm); + BOOST_CHECK_EQUAL(gapCyl.get(CylinderVolumeBounds::eMaxR), 20_mm); + BOOST_CHECK_EQUAL(gapCyl.get(CylinderVolumeBounds::eHalfLengthZ), 6_mm); + } +} + +BOOST_AUTO_TEST_CASE(Confined) { + Transform3 base{Transform3::Identity()}; + + Blueprint::Config cfg; + cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; + cfg.envelope[BinningValue::binR] = {2_mm, 20_mm}; + auto root = std::make_unique(cfg); + + root->addStaticVolume( + base, std::make_shared(50_mm, 400_mm, 1000_mm), + "PixelWrapper", [&](auto& wrap) { + double rMin = 100_mm; + double rMax = 350_mm; + double hlZ = 100_mm; + + wrap.addStaticVolume( + base * Translation3{Vector3{0, 0, -600_mm}}, + std::make_shared(rMin, rMax, hlZ), + "PixelNeg1"); + + wrap.addStaticVolume( + base * Translation3{Vector3{0, 0, -200_mm}}, + std::make_shared(rMin, rMax, hlZ), + "PixelNeg2"); + + wrap.addStaticVolume( + base * Translation3{Vector3{0, 0, 200_mm}}, + std::make_shared(rMin, rMax, hlZ), + "PixelPos1"); + + wrap.addStaticVolume( + base * Translation3{Vector3{0, 0, 600_mm}}, + std::make_shared(rMin, rMax, hlZ), + "PixelPos2"); + }); + + auto trackingGeometry = root->construct({}, gctx, *logger); + + // overall dimensions are the wrapper volume + envelope + auto lookup = nameLookup(*trackingGeometry); + auto worldCyl = + dynamic_cast(lookup("World").volumeBounds()); + BOOST_CHECK_EQUAL(worldCyl.get(CylinderVolumeBounds::eMinR), 48_mm); + BOOST_CHECK_EQUAL(worldCyl.get(CylinderVolumeBounds::eMaxR), 420_mm); + BOOST_CHECK_EQUAL(worldCyl.get(CylinderVolumeBounds::eHalfLengthZ), 1020_mm); + + // 4 outer portals and 4 inner + BOOST_CHECK_EQUAL(lookup("World").portals().size(), 8); + BOOST_CHECK_EQUAL(lookup("World").volumes().size(), 1); + + auto wrapperCyl = dynamic_cast( + lookup("PixelWrapper").volumeBounds()); + BOOST_CHECK_EQUAL(wrapperCyl.get(CylinderVolumeBounds::eMinR), 50_mm); + BOOST_CHECK_EQUAL(wrapperCyl.get(CylinderVolumeBounds::eMaxR), 400_mm); + BOOST_CHECK_EQUAL(wrapperCyl.get(CylinderVolumeBounds::eHalfLengthZ), + 1000_mm); + BOOST_CHECK_EQUAL(lookup("PixelWrapper").portals().size(), 4 + 4 * 4); + BOOST_CHECK_EQUAL(lookup("PixelWrapper").volumes().size(), 4); + + for (const auto& name : + {"PixelNeg1", "PixelNeg2", "PixelPos1", "PixelPos2"}) { + auto actCyl = + dynamic_cast(lookup(name).volumeBounds()); + BOOST_CHECK_EQUAL(actCyl.get(CylinderVolumeBounds::eMinR), 100_mm); + BOOST_CHECK_EQUAL(actCyl.get(CylinderVolumeBounds::eMaxR), 350_mm); + BOOST_CHECK_EQUAL(actCyl.get(CylinderVolumeBounds::eHalfLengthZ), 100_mm); + BOOST_CHECK_EQUAL(lookup(name).portals().size(), 4); + } +} + +BOOST_AUTO_TEST_CASE(DiscLayer) { + double yrot = 45_degree; + Transform3 base = Transform3::Identity() * AngleAxis3{yrot, Vector3::UnitY()}; + + std::vector> surfaces; + std::vector> elements; + double r = 300_mm; + std::size_t nSensors = 8; + double thickness = 2.5_mm; + auto recBounds = std::make_shared(40_mm, 60_mm); + + double deltaPhi = 2 * std::numbers::pi / nSensors; + for (std::size_t i = 0; i < nSensors; i++) { + // Create a fan of sensors + + Transform3 trf = base * AngleAxis3{deltaPhi * i, Vector3::UnitZ()} * + Translation3(Vector3::UnitX() * r); + + if (i % 2 == 0) { + trf = trf * Translation3{Vector3::UnitZ() * 5_mm}; + } + + auto& element = elements.emplace_back( + std::make_unique(trf, recBounds, thickness)); + + element->surface().assignDetectorElement(*element); + + surfaces.push_back(element->surface().getSharedPtr()); + } + + Blueprint root{{.envelope = ExtentEnvelope{{ + .z = {2_mm, 2_mm}, + .r = {3_mm, 5_mm}, + }}}}; + + root.addLayer("Layer0", [&](auto& layer) { + layer.setSurfaces(surfaces) + .setLayerType(LayerBlueprintNode::LayerType::Disc) + .setEnvelope(ExtentEnvelope{{ + .z = {0.1_mm, 0.1_mm}, + .r = {1_mm, 1_mm}, + }}) + .setTransform(base); + }); + + auto trackingGeometry = root.construct({}, gctx, *logger); + + std::size_t nSurfaces = 0; + + trackingGeometry->visitSurfaces([&](const Surface* surface) { + if (surface->associatedDetectorElement() != nullptr) { + nSurfaces++; + } + }); + + BOOST_CHECK_EQUAL(nSurfaces, surfaces.size()); + BOOST_CHECK_EQUAL(countVolumes(*trackingGeometry), 2); + auto lookup = nameLookup(*trackingGeometry); + auto layerCyl = dynamic_cast( + lookup("Layer0").volumeBounds()); + BOOST_CHECK_CLOSE(layerCyl.get(CylinderVolumeBounds::eMinR), 258.9999999_mm, + 1e-6); + BOOST_CHECK_CLOSE(layerCyl.get(CylinderVolumeBounds::eMaxR), 346.25353003_mm, + 1e-6); + BOOST_CHECK_CLOSE(layerCyl.get(CylinderVolumeBounds::eHalfLengthZ), 3.85_mm, + 1e-6); +} + +BOOST_AUTO_TEST_CASE(CylinderLayer) { + double yrot = 0_degree; + Transform3 base = Transform3::Identity() * AngleAxis3{yrot, Vector3::UnitY()}; + + std::vector> surfaces; + std::vector> elements; + + double r = 300_mm; + std::size_t nStaves = 10; + int nSensorsPerStave = 8; + double thickness = 0; + double hlPhi = 40_mm; + double hlZ = 60_mm; + auto recBounds = std::make_shared(hlPhi, hlZ); + + double deltaPhi = 2 * std::numbers::pi / nStaves; + + for (std::size_t istave = 0; istave < nStaves; istave++) { + for (int isensor = -nSensorsPerStave; isensor <= nSensorsPerStave; + isensor++) { + double z = isensor * (2 * hlZ + 5_mm); + + Transform3 trf = base * Translation3(Vector3::UnitZ() * z) * + AngleAxis3{deltaPhi * istave, Vector3::UnitZ()} * + Translation3(Vector3::UnitX() * r) * + AngleAxis3{10_degree, Vector3::UnitZ()} * + AngleAxis3{90_degree, Vector3::UnitY()} * + AngleAxis3{90_degree, Vector3::UnitZ()}; + auto& element = elements.emplace_back( + std::make_unique(trf, recBounds, thickness)); + element->surface().assignDetectorElement(*element); + surfaces.push_back(element->surface().getSharedPtr()); + } + } + + Blueprint root{{.envelope = ExtentEnvelope{{ + .z = {2_mm, 2_mm}, + .r = {3_mm, 5_mm}, + }}}}; + + root.addLayer("Layer0", [&](auto& layer) { + layer.setSurfaces(surfaces) + .setLayerType(LayerBlueprintNode::LayerType::Cylinder) + .setEnvelope(ExtentEnvelope{{ + .z = {10_mm, 10_mm}, + .r = {20_mm, 10_mm}, + }}) + .setTransform(base); + }); + + auto trackingGeometry = root.construct({}, gctx, *logger); + + std::size_t nSurfaces = 0; + + trackingGeometry->visitSurfaces([&](const Surface* surface) { + if (surface->associatedDetectorElement() != nullptr) { + nSurfaces++; + } + }); + + BOOST_CHECK_EQUAL(nSurfaces, surfaces.size()); + BOOST_CHECK_EQUAL(countVolumes(*trackingGeometry), 2); + auto lookup = nameLookup(*trackingGeometry); + auto layerCyl = dynamic_cast( + lookup("Layer0").volumeBounds()); + BOOST_CHECK_EQUAL(lookup("Layer0").portals().size(), 4); + BOOST_CHECK_CLOSE(layerCyl.get(CylinderVolumeBounds::eMinR), 275.6897761_mm, + 1e-6); + BOOST_CHECK_CLOSE(layerCyl.get(CylinderVolumeBounds::eMaxR), 319.4633358_mm, + 1e-6); + BOOST_CHECK_CLOSE(layerCyl.get(CylinderVolumeBounds::eHalfLengthZ), 1070_mm, + 1e-6); +} + +BOOST_AUTO_TEST_CASE(Material) { + Blueprint::Config cfg; + cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; + cfg.envelope[BinningValue::binR] = {1_mm, 2_mm}; + Blueprint root{cfg}; + + ActsScalar hlZ = 30_mm; + auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); + auto cyl = std::make_unique(Transform3::Identity(), cylBounds, + "child"); + + using enum BinningValue; + using enum CylinderVolumeBounds::Face; + using enum AxisBoundaryType; + + root.addMaterial("Material", [&](auto& mat) { + // @TODO: This API is not great + mat.setBinning(std::vector{ + std::tuple{NegativeDisc, Experimental::ProtoBinning{binR, Bound, 5}, + Experimental::ProtoBinning{binPhi, Bound, 10}}, + std::tuple{PositiveDisc, Experimental::ProtoBinning{binR, Bound, 15}, + Experimental::ProtoBinning{binPhi, Bound, 20}}, + }); + + mat.addStaticVolume(std::move(cyl)); + }); + + auto trackingGeometry = root.construct({}, gctx, *logger); + + BOOST_CHECK_EQUAL(countVolumes(*trackingGeometry), 2); + auto lookup = nameLookup(*trackingGeometry); + auto& child = lookup("child"); + + const auto* negDisc = child.portals().at(0).surface().surfaceMaterial(); + const auto* posDisc = child.portals().at(1).surface().surfaceMaterial(); + BOOST_CHECK_NE(negDisc, nullptr); + BOOST_CHECK_NE(posDisc, nullptr); + + const auto& negDiscMat = + dynamic_cast(*negDisc); + const auto& posDiscMat = + dynamic_cast(*posDisc); + + BOOST_CHECK_EQUAL(negDiscMat.binning().binning.at(0).bins(), 5); + BOOST_CHECK_EQUAL(negDiscMat.binning().binning.at(1).bins(), 10); + BOOST_CHECK_EQUAL(posDiscMat.binning().binning.at(0).bins(), 15); + BOOST_CHECK_EQUAL(posDiscMat.binning().binning.at(1).bins(), 20); + + for (std::size_t i = 2; i < child.portals().size(); i++) { + BOOST_CHECK_EQUAL(child.portals().at(i).surface().surfaceMaterial(), + nullptr); + } +} + +BOOST_AUTO_TEST_SUITE_END(); + +BOOST_AUTO_TEST_SUITE_END(); + +} // namespace Acts::Test diff --git a/Tests/UnitTests/Core/Geometry/CMakeLists.txt b/Tests/UnitTests/Core/Geometry/CMakeLists.txt index 39d7abc3740..41c218129fe 100644 --- a/Tests/UnitTests/Core/Geometry/CMakeLists.txt +++ b/Tests/UnitTests/Core/Geometry/CMakeLists.txt @@ -35,4 +35,5 @@ add_unittest(CylinderVolumeStack CylinderVolumeStackTests.cpp) add_unittest(PortalLink PortalLinkTests.cpp) add_unittest(Portal PortalTests.cpp) add_unittest(PortalShell PortalShellTests.cpp) +add_unittest(Blueprint BlueprintTests.cpp) add_unittest(BlueprintApi BlueprintApiTests.cpp) From 75fc0986042313b02ef2a056efeb4cbce3d5d47e Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Wed, 27 Nov 2024 17:10:53 +0100 Subject: [PATCH 066/100] remove some code from the python test --- Examples/Python/tests/test_blueprint.py | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/Examples/Python/tests/test_blueprint.py b/Examples/Python/tests/test_blueprint.py index d79f60f03cd..6964be2abff 100644 --- a/Examples/Python/tests/test_blueprint.py +++ b/Examples/Python/tests/test_blueprint.py @@ -65,25 +65,3 @@ def write(root: acts.BlueprintNode, stage: int): ec.addStaticVolume(trf, bounds, name=f"pEC_{i}") write(root, 4) - - # gz = tmp_path / "blueprint.dot" - # print(gz) - # with gz.open("w") as fh: - # root.graphViz(fh) - # - # trackingGeometry = root.construct( - # acts.BlueprintNode.Options(), gctx, level=logLevel - # ) - # assert trackingGeometry is not None - - -if False: - with root.CylinderContainer("Detector", direction=bv.binZ) as det: - det.addStaticVolume( - base, acts.CylinderVolumeBounds(0, 23 * mm, 3 * m), "BeamPipe" - ) - - trackingGeometry = root.construct( - acts.BlueprintNode.Options(), gctx, level=logLevel - ) - assert trackingGeometry is not None From 3c90aa0791a191d622c8a6e2932dbcac5fac9e27 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Thu, 28 Nov 2024 10:57:10 +0100 Subject: [PATCH 067/100] blueprint: Remove ActsScalar --- Core/src/Geometry/LayerBlueprintNode.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Core/src/Geometry/LayerBlueprintNode.cpp b/Core/src/Geometry/LayerBlueprintNode.cpp index dbf0439a6ec..b126c2280e1 100644 --- a/Core/src/Geometry/LayerBlueprintNode.cpp +++ b/Core/src/Geometry/LayerBlueprintNode.cpp @@ -59,16 +59,16 @@ void LayerBlueprintNode::buildVolume(const Extent& extent, switch (m_layerType) { case Cylinder: case Disc: { - ActsScalar minR = extent.min(binR); - ActsScalar maxR = extent.max(binR); - ActsScalar hlZ = extent.interval(binZ) / 2.0; + double minR = extent.min(binR); + double maxR = extent.max(binR); + double hlZ = extent.interval(binZ) / 2.0; bounds = std::make_shared(minR, maxR, hlZ); break; } case Plane: { - ActsScalar hlX = extent.interval(binX) / 2.0; - ActsScalar hlY = extent.interval(binY) / 2.0; - ActsScalar hlZ = extent.interval(binZ) / 2.0; + double hlX = extent.interval(binX) / 2.0; + double hlY = extent.interval(binY) / 2.0; + double hlZ = extent.interval(binZ) / 2.0; bounds = std::make_shared(hlX, hlY, hlZ); break; } From e75a401c82939ee853afc68049f40bf4bdbcf9af Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 2 Dec 2024 10:56:10 +0100 Subject: [PATCH 068/100] remove ActsScalar from blueprint tests --- Tests/UnitTests/Core/Geometry/BlueprintTests.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp index b339167239d..d123a3e66fd 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp @@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE(Static) { cfg.envelope[BinningValue::binR] = {1_mm, 2_mm}; Blueprint root{cfg}; - ActsScalar hlZ = 30_mm; + double hlZ = 30_mm; auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); auto cyl = std::make_unique(Transform3::Identity(), cylBounds, "child"); @@ -138,8 +138,8 @@ BOOST_AUTO_TEST_CASE(CylinderContainer) { auto& cyl = root->addCylinderContainer("Container", BinningValue::binZ); cyl.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap); - ActsScalar z0 = -200_mm; - ActsScalar hlZ = 30_mm; + double z0 = -200_mm; + double hlZ = 30_mm; auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); for (std::size_t i = 0; i < 3; i++) { auto childCyl = std::make_unique( @@ -398,7 +398,7 @@ BOOST_AUTO_TEST_CASE(Material) { cfg.envelope[BinningValue::binR] = {1_mm, 2_mm}; Blueprint root{cfg}; - ActsScalar hlZ = 30_mm; + double hlZ = 30_mm; auto cylBounds = std::make_shared(10_mm, 20_mm, hlZ); auto cyl = std::make_unique(Transform3::Identity(), cylBounds, "child"); From c7a109ec9492d1a9e8c274b225664cf14dfc6273 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 3 Dec 2024 12:39:54 +0100 Subject: [PATCH 069/100] fix unit test --- Tests/UnitTests/Core/Geometry/BlueprintTests.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp index d123a3e66fd..542b6ea1a28 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp @@ -72,6 +72,8 @@ BOOST_AUTO_TEST_SUITE(Geometry); BOOST_AUTO_TEST_SUITE(BlueprintNodeTest); BOOST_AUTO_TEST_CASE(InvalidRoot) { + Logging::ScopedFailureThreshold threshold{Logging::Level::FATAL}; + Blueprint::Config cfg; Blueprint root{cfg}; BOOST_CHECK_THROW(root.construct({}, gctx, *logger), std::logic_error); From 4a1ffb540688fb52b83ca5cfee5337bad1fa8d5a Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 3 Dec 2024 16:32:27 +0100 Subject: [PATCH 070/100] minimal docs update --- docs/core/geometry/concepts.md | 42 +++++++++++++++++++++++ docs/core/geometry/construction.md | 28 +++++++++++++++ docs/core/geometry/index.md | 3 ++ docs/core/geometry/layerless/layerless.md | 6 ++-- 4 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 docs/core/geometry/concepts.md create mode 100644 docs/core/geometry/construction.md diff --git a/docs/core/geometry/concepts.md b/docs/core/geometry/concepts.md new file mode 100644 index 00000000000..7575a5cb610 --- /dev/null +++ b/docs/core/geometry/concepts.md @@ -0,0 +1,42 @@ +# Concepts + +:::{todo} +Not complete yet +::: + +## Tracking geometry + +## Volume + +### Volume bounds + +## Tracking volume + +## Portals + +:::{doxygenclass} Acts::Portal +::: + +### Portal links + +:::{doxygenclass} Acts::PortalLinkBase +::: + +#### Trivial portal link + +:::{doxygenclass} Acts::TrivialPortalLink +::: + +#### Grid portal link + +:::{doxygenclass} Acts::GridPortalLink +::: + +#### Composite portal link + +:::{doxygenclass} Acts::CompositePortalLink +::: + +### Portal shells + +### Navigation policy diff --git a/docs/core/geometry/construction.md b/docs/core/geometry/construction.md new file mode 100644 index 00000000000..44c38ed3022 --- /dev/null +++ b/docs/core/geometry/construction.md @@ -0,0 +1,28 @@ +# Construction + +:::{todo} +Not complete yet +::: + +## Blueprint tracking geometry construction + +:::{doxygenclass} Acts::BlueprintNode +::: + +### Container nodes + +### Material nodes + +### Geometry identification specification + +### *Layers* + +## API + +### C++ API Example + +### Python API Examples + +### Plugin usage + +### Extension capabilities diff --git a/docs/core/geometry/index.md b/docs/core/geometry/index.md index b0009a36ef1..2bcb5cdec3f 100644 --- a/docs/core/geometry/index.md +++ b/docs/core/geometry/index.md @@ -1,4 +1,5 @@ (geometry_impl)= + # Geometry module The ACTS geometry model is strongly based on the ATLAS Tracking geometry. Its @@ -15,9 +16,11 @@ logical layers will be modelled as volumes, see [](layerless_geometry). :::{toctree} :maxdepth: 1 +concepts geometry_id material surfaces legacy/legacy +construction layerless/layerless ::: diff --git a/docs/core/geometry/layerless/layerless.md b/docs/core/geometry/layerless/layerless.md index b9784ac1f74..7fdc0d83516 100644 --- a/docs/core/geometry/layerless/layerless.md +++ b/docs/core/geometry/layerless/layerless.md @@ -1,13 +1,13 @@ (layerless_geometry)= + # Layerless geometry ## Geometry module rosetta stone -:::{todo} -Describe replacements of `TrackingGeometry`, `TrackingVolume` etc. and how the classes map to one another. +:::{note} +The combination of the original (Gen 1) geometry classes and the new *layerless* modelling (Gen 2, this page) will result in a combined Gen 3 geometry model. It will be documented [here](core/geometry/index.md) when completed. ::: - :::{toctree} building ::: From 71bdcec9094bb82bb5f56d05f7b0911736fcb2b8 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 3 Dec 2024 16:52:07 +0100 Subject: [PATCH 071/100] pull out BlueprintOptions into separate files --- Core/include/Acts/Geometry/Blueprint.hpp | 8 ++---- Core/include/Acts/Geometry/BlueprintNode.hpp | 21 ++++---------- .../Acts/Geometry/BlueprintOptions.hpp | 28 +++++++++++++++++++ .../CylinderContainerBlueprintNode.hpp | 6 ++-- .../Acts/Geometry/LayerBlueprintNode.hpp | 4 +-- .../MaterialDesignatorBlueprintNode.hpp | 6 ++-- .../Acts/Geometry/StaticBlueprintNode.hpp | 6 ++-- Core/src/Geometry/Blueprint.cpp | 11 ++++---- Core/src/Geometry/BlueprintNode.cpp | 13 --------- Core/src/Geometry/BlueprintOptions.cpp | 28 +++++++++++++++++++ Core/src/Geometry/CMakeLists.txt | 1 + .../CylinderContainerBlueprintNode.cpp | 7 +++-- Core/src/Geometry/LayerBlueprintNode.cpp | 4 +-- .../MaterialDesignatorBlueprintNode.cpp | 7 +++-- Core/src/Geometry/StaticBlueprintNode.cpp | 6 ++-- Examples/Python/src/Blueprint.cpp | 6 ++-- 16 files changed, 98 insertions(+), 64 deletions(-) create mode 100644 Core/include/Acts/Geometry/BlueprintOptions.hpp create mode 100644 Core/src/Geometry/BlueprintOptions.cpp diff --git a/Core/include/Acts/Geometry/Blueprint.hpp b/Core/include/Acts/Geometry/Blueprint.hpp index b98f642bdf4..ceedffbd775 100644 --- a/Core/include/Acts/Geometry/Blueprint.hpp +++ b/Core/include/Acts/Geometry/Blueprint.hpp @@ -27,8 +27,6 @@ class Blueprint : private BlueprintNode { using BlueprintNode::children; using BlueprintNode::graphViz; - using BlueprintNode::Options; - struct Config { ExtentEnvelope envelope = ExtentEnvelope::Zero(); GeometryIdentifierHook geometryIdentifierHook = {}; @@ -43,14 +41,14 @@ class Blueprint : private BlueprintNode { const Logger& logger = Acts::getDummyLogger()); protected: - Volume& build(const Options& options, const GeometryContext& gctx, + Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; PortalShellBase& connect( - const Options& options, const GeometryContext& gctx, + const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(const Options& options, const GeometryContext& gctx, + void finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override; diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index 7ffeb044dd6..c0785c86d56 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -9,6 +9,7 @@ #pragma once #include "Acts/Definitions/Algebra.hpp" +#include "Acts/Geometry/BlueprintOptions.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Geometry/NavigationPolicyFactory.hpp" #include "Acts/Utilities/BinningType.hpp" @@ -33,17 +34,6 @@ class LayerBlueprintNode; class BlueprintNode { public: - struct Options { - std::unique_ptr defaultNavigationPolicyFactory{ - makeDefaultNavigationPolicyFactory()}; - - void validate() const; - - private: - static std::unique_ptr - makeDefaultNavigationPolicyFactory(); - }; - BlueprintNode() = default; virtual ~BlueprintNode() = default; @@ -52,15 +42,16 @@ class BlueprintNode { virtual void toStream(std::ostream& os) const; - virtual Volume& build(const Options& options, const GeometryContext& gctx, + virtual Volume& build(const BlueprintOptions& options, + const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) = 0; virtual PortalShellBase& connect( - const Options& options, const GeometryContext& gctx, + const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) = 0; - virtual void finalize(const Options& options, const GeometryContext& gctx, - TrackingVolume& parent, + virtual void finalize(const BlueprintOptions& options, + const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) = 0; StaticBlueprintNode& addStaticVolume( diff --git a/Core/include/Acts/Geometry/BlueprintOptions.hpp b/Core/include/Acts/Geometry/BlueprintOptions.hpp new file mode 100644 index 00000000000..ca276289d51 --- /dev/null +++ b/Core/include/Acts/Geometry/BlueprintOptions.hpp @@ -0,0 +1,28 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include + +namespace Acts { + +class NavigationPolicyFactory; + +struct BlueprintOptions { + std::unique_ptr defaultNavigationPolicyFactory{ + makeDefaultNavigationPolicyFactory()}; + + void validate() const; + + private: + static std::unique_ptr + makeDefaultNavigationPolicyFactory(); +}; + +} // namespace Acts diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index 9e18fb4f579..6857a5a26bb 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -31,14 +31,14 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { void setName(const std::string& name) { m_name = name; } - Volume& build(const Options& options, const GeometryContext& gctx, + Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; CylinderStackPortalShell& connect( - const Options& options, const GeometryContext& gctx, + const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(const Options& options, const GeometryContext& gctx, + void finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) override; CylinderContainerBlueprintNode& setDirection(BinningValue direction); diff --git a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp index 1d8bb98be8c..1dbe03e20be 100644 --- a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp @@ -23,10 +23,10 @@ class LayerBlueprintNode : public StaticBlueprintNode { const std::string& name() const override; - Volume& build(const Options& options, const GeometryContext& gctx, + Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(const Options& options, const GeometryContext& gctx, + void finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override; diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index f099318cda4..7d5c5a79bbf 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -31,14 +31,14 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { void toStream(std::ostream& os) const override; - Volume& build(const Options& options, const GeometryContext& gctx, + Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; PortalShellBase& connect( - const Options& options, const GeometryContext& gctx, + const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(const Options& options, const GeometryContext& gctx, + void finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) override; void addToGraphviz(std::ostream& os) const override; diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index 136996e4281..ec57d0d2dad 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -21,15 +21,15 @@ class StaticBlueprintNode : public BlueprintNode { const std::string& name() const override; - Volume& build(const Options& options, const GeometryContext& gctx, + Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; PortalShellBase& connect( - const Options& options, const GeometryContext& gctx, + const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(const Options& options, const GeometryContext& gctx, + void finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override; diff --git a/Core/src/Geometry/Blueprint.cpp b/Core/src/Geometry/Blueprint.cpp index 56de14c0f5d..0d7817aebba 100644 --- a/Core/src/Geometry/Blueprint.cpp +++ b/Core/src/Geometry/Blueprint.cpp @@ -18,26 +18,26 @@ namespace Acts { -Blueprint::Blueprint(const Config &cfg) : m_cfg(cfg) {} +Blueprint::Blueprint(const Config &config) : m_cfg(config) {} const std::string &Blueprint::name() const { static const std::string root = "root"; return root; } -Volume &Blueprint::build(const Options & /*options*/, +Volume &Blueprint::build(const BlueprintOptions & /*options*/, const GeometryContext & /*gctx*/, const Logger & /*logger*/) { throw std::logic_error("Root node cannot be built"); } -PortalShellBase &Blueprint::connect(const Options & /*options*/, +PortalShellBase &Blueprint::connect(const BlueprintOptions & /*options*/, const GeometryContext & /*gctx*/, const Logger & /*logger*/) { throw std::logic_error("Root node cannot be connected"); } -void Blueprint::finalize(const Options & /*options*/, +void Blueprint::finalize(const BlueprintOptions & /*options*/, const GeometryContext & /*gctx*/, TrackingVolume & /*parent*/, const Logger & /*logger*/) { @@ -53,7 +53,8 @@ void Blueprint::addToGraphviz(std::ostream &os) const { } std::unique_ptr Blueprint::construct( - const Options &options, const GeometryContext &gctx, const Logger &logger) { + const BlueprintOptions &options, const GeometryContext &gctx, + const Logger &logger) { using enum BinningValue; ACTS_INFO(prefix() << "Building tracking geometry from blueprint tree"); diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index f11f6ec60a0..6c6561570c6 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -49,19 +49,6 @@ std::string BlueprintNode::prefix() const { return indent() + "[" + name() + "]: "; } -void BlueprintNode::Options::validate() const { - if (!defaultNavigationPolicyFactory) { - throw std::invalid_argument("Navigation policy factory is nullptr"); - } -} - -std::unique_ptr -BlueprintNode::Options::makeDefaultNavigationPolicyFactory() { - return NavigationPolicyFactory::make() - .add() - .asUniquePtr(); -} - StaticBlueprintNode& BlueprintNode::addStaticVolume( std::unique_ptr volume, const std::function& callback) { diff --git a/Core/src/Geometry/BlueprintOptions.cpp b/Core/src/Geometry/BlueprintOptions.cpp new file mode 100644 index 00000000000..b1b46173116 --- /dev/null +++ b/Core/src/Geometry/BlueprintOptions.cpp @@ -0,0 +1,28 @@ +// This file is part of the ACTS project. +// +// Copyright (C) 2016 CERN for the benefit of the ACTS project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Acts/Geometry/BlueprintOptions.hpp" + +#include "Acts/Geometry/NavigationPolicyFactory.hpp" +#include "Acts/Navigation/TryAllNavigationPolicy.hpp" + +namespace Acts { + +void BlueprintOptions::validate() const { + if (!defaultNavigationPolicyFactory) { + throw std::invalid_argument("Navigation policy factory is nullptr"); + } +} + +std::unique_ptr +BlueprintOptions::makeDefaultNavigationPolicyFactory() { + return NavigationPolicyFactory::make() + .add() + .asUniquePtr(); +} +} // namespace Acts diff --git a/Core/src/Geometry/CMakeLists.txt b/Core/src/Geometry/CMakeLists.txt index 6fcf65eb46e..189c4396112 100644 --- a/Core/src/Geometry/CMakeLists.txt +++ b/Core/src/Geometry/CMakeLists.txt @@ -45,6 +45,7 @@ target_sources( PortalShell.cpp BlueprintNode.cpp Blueprint.cpp + BlueprintOptions.cpp CylinderContainerBlueprintNode.cpp StaticBlueprintNode.cpp LayerBlueprintNode.cpp diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index e4164ce4d42..a0dce32f89a 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -35,7 +35,7 @@ const std::string& CylinderContainerBlueprintNode::name() const { return m_name; } -Volume& CylinderContainerBlueprintNode::build(const Options& options, +Volume& CylinderContainerBlueprintNode::build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger) { ACTS_DEBUG(prefix() << "cylinder container build (dir=" << m_direction @@ -68,7 +68,8 @@ Volume& CylinderContainerBlueprintNode::build(const Options& options, } CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( - const Options& options, const GeometryContext& gctx, const Logger& logger) { + const BlueprintOptions& options, const GeometryContext& gctx, + const Logger& logger) { ACTS_DEBUG(prefix() << "Cylinder container connect"); if (m_stack == nullptr) { ACTS_ERROR(prefix() << "Volume is not built"); @@ -145,7 +146,7 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( return *m_shell; } -void CylinderContainerBlueprintNode::finalize(const Options& options, +void CylinderContainerBlueprintNode::finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) { diff --git a/Core/src/Geometry/LayerBlueprintNode.cpp b/Core/src/Geometry/LayerBlueprintNode.cpp index b126c2280e1..2dd67faf7d9 100644 --- a/Core/src/Geometry/LayerBlueprintNode.cpp +++ b/Core/src/Geometry/LayerBlueprintNode.cpp @@ -17,7 +17,7 @@ namespace Acts { -Volume& LayerBlueprintNode::build(const BlueprintNode::Options& options, +Volume& LayerBlueprintNode::build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger) { if (m_surfaces.empty()) { @@ -88,7 +88,7 @@ void LayerBlueprintNode::buildVolume(const Extent& extent, std::make_unique(transform, std::move(bounds), m_name); } -void LayerBlueprintNode::finalize(const BlueprintNode::Options& options, +void LayerBlueprintNode::finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) { diff --git a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp index b0db3001ad7..465fb8c0821 100644 --- a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp +++ b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp @@ -26,7 +26,7 @@ void MaterialDesignatorBlueprintNode::toStream(std::ostream& os) const { os << "MaterialDesignatorBlueprintNode(" << name() << ")"; } -Volume& MaterialDesignatorBlueprintNode::build(const Options& options, +Volume& MaterialDesignatorBlueprintNode::build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger) { if (children().size() != 1) { @@ -40,7 +40,8 @@ Volume& MaterialDesignatorBlueprintNode::build(const Options& options, } PortalShellBase& MaterialDesignatorBlueprintNode::connect( - const Options& options, const GeometryContext& gctx, const Logger& logger) { + const BlueprintOptions& options, const GeometryContext& gctx, + const Logger& logger) { ACTS_DEBUG(prefix() << "MaterialDesignatorBlueprintNode::connect"); if (children().size() != 1) { ACTS_ERROR(prefix() << "MaterialDesignatorBlueprintNode must have exactly " @@ -125,7 +126,7 @@ PortalShellBase& MaterialDesignatorBlueprintNode::connect( return shell; } -void MaterialDesignatorBlueprintNode::finalize(const Options& options, +void MaterialDesignatorBlueprintNode::finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) { diff --git a/Core/src/Geometry/StaticBlueprintNode.cpp b/Core/src/Geometry/StaticBlueprintNode.cpp index c227fa8e1b8..12defdcc2eb 100644 --- a/Core/src/Geometry/StaticBlueprintNode.cpp +++ b/Core/src/Geometry/StaticBlueprintNode.cpp @@ -20,7 +20,7 @@ namespace Acts { StaticBlueprintNode::StaticBlueprintNode(std::unique_ptr volume) : m_volume(std::move(volume)) {} -Volume& StaticBlueprintNode::build(const Options& options, +Volume& StaticBlueprintNode::build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger) { ACTS_DEBUG(prefix() << "static build"); @@ -38,7 +38,7 @@ Volume& StaticBlueprintNode::build(const Options& options, return *m_volume; } -PortalShellBase& StaticBlueprintNode::connect(const Options& options, +PortalShellBase& StaticBlueprintNode::connect(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger) { ACTS_DEBUG(prefix() << "Static connect"); @@ -73,7 +73,7 @@ PortalShellBase& StaticBlueprintNode::connect(const Options& options, return *m_shell; } -void StaticBlueprintNode::finalize(const Options& options, +void StaticBlueprintNode::finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) { diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 1294aa8461e..d0a35d06f85 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -259,8 +259,7 @@ void addBlueprint(Context& ctx) { // @TODO: Add ability to provide policy factories // This needs a way to produce them in python! - py::class_(blueprintNode, "Options") - .def(py::init<>()); + py::class_(m, "BlueprintOptions").def(py::init<>()); py::class_(blueprintNode, "MutableChildRange") @@ -288,12 +287,11 @@ void addBlueprint(Context& ctx) { auto n = py::class_>(m, "Blueprint"); n.def(py::init()) - .def_property_readonly("name", &Blueprint::name) // Return value needs to be shared pointer because python otherwise // can't manage the lifetime .def( "construct", - [](Blueprint& self, const Blueprint::Options& options, + [](Blueprint& self, const BlueprintOptions& options, const GeometryContext& gctx, Logging::Level level) -> std::shared_ptr { return self.construct(options, gctx, From 70ca53ae08b9b1488031cde2c723b01d668da713 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 3 Dec 2024 18:03:36 +0100 Subject: [PATCH 072/100] fix Portal related doc strings (markdown) --- Core/include/Acts/Geometry/CompositePortalLink.hpp | 2 ++ Core/include/Acts/Geometry/GridPortalLink.hpp | 12 ++++++++++++ Core/include/Acts/Geometry/Portal.hpp | 4 ++++ 3 files changed, 18 insertions(+) diff --git a/Core/include/Acts/Geometry/CompositePortalLink.hpp b/Core/include/Acts/Geometry/CompositePortalLink.hpp index 6586d875b79..231af047b6c 100644 --- a/Core/include/Acts/Geometry/CompositePortalLink.hpp +++ b/Core/include/Acts/Geometry/CompositePortalLink.hpp @@ -23,6 +23,7 @@ class Surface; /// Composite portal links can graft together other portal link instances, for /// example grids that could not be merged due to invalid binnings. /// +/// ``` /// +-------+ +-------+ /// | | | | /// | | | | @@ -36,6 +37,7 @@ class Surface; /// | | +-------+ /// | | | | /// +-------+ +-------+ +/// ``` /// /// During resolution, it will consult each of it's children and return /// the result on the first surface where the lookup position is within diff --git a/Core/include/Acts/Geometry/GridPortalLink.hpp b/Core/include/Acts/Geometry/GridPortalLink.hpp index 8bf1d06ee08..94e98867905 100644 --- a/Core/include/Acts/Geometry/GridPortalLink.hpp +++ b/Core/include/Acts/Geometry/GridPortalLink.hpp @@ -111,6 +111,7 @@ class GridPortalLink : public PortalLinkBase { /// /// 1D merge scenarios: /// + /// ``` /// +----------------------------------------------------------+ /// |Colinear | /// | | @@ -126,9 +127,11 @@ class GridPortalLink : public PortalLinkBase { /// | +-------+-------+-------+-------+-------+-------+ | /// | | /// +----------------------------------------------------------+ + /// ``` /// /// Two grid along a shared direction are merged along their shared direction /// + /// ``` /// +-------------------------------------------------+ /// |Parallel | /// | | @@ -147,10 +150,12 @@ class GridPortalLink : public PortalLinkBase { /// | +-------+ +-------+ +-------+-------+ | /// | | /// +-------------------------------------------------+ + /// ``` /// /// Two grids along a shared direction a merged in the direction that is /// orthogonal to their shared direction. /// + /// ``` /// +-------------------------------------------+ /// |Perpendicular | /// | | @@ -180,6 +185,7 @@ class GridPortalLink : public PortalLinkBase { /// | +-------+-------+-------+ | /// | | /// +-------------------------------------------+ + /// ``` /// /// Two grids whose directions are not shared are merged (ordering does not /// matter here). The routine will expand one of the grids to match the @@ -192,6 +198,7 @@ class GridPortalLink : public PortalLinkBase { /// side. The 1D grid is expanded to match the binning in the as-of-yet /// unbinned direction with the binning taken from the 2D grid. /// + /// ``` /// +-----------------------------------------+ /// |2D + 1D | /// | | @@ -215,7 +222,9 @@ class GridPortalLink : public PortalLinkBase { /// | | | | | /// | +-------+-------+ | /// +-----------------------------------------+ + /// ``` /// + /// ``` /// +--------------------------------------------------------------+ /// |2D + 1D | /// | | @@ -234,6 +243,7 @@ class GridPortalLink : public PortalLinkBase { /// | +-------+-------+ +-------+ +-------+-------+-------+ | /// | | /// +--------------------------------------------------------------+ + /// ``` /// /// 2D merges /// The grids need to already share a common axis. If that is not the case, @@ -241,6 +251,7 @@ class GridPortalLink : public PortalLinkBase { /// merging as a fallback if needed. /// Ordering and direction does not matter here. /// + /// ``` /// +-----------------------------------------+ /// |2D + 2D | /// | | @@ -273,6 +284,7 @@ class GridPortalLink : public PortalLinkBase { /// | +-------+-------+-------+-------+ | /// | | /// +-----------------------------------------+ + /// ``` /// /// @param a The first grid portal link /// @param b The second grid portal link diff --git a/Core/include/Acts/Geometry/Portal.hpp b/Core/include/Acts/Geometry/Portal.hpp index 722b433d036..3d1a065026f 100644 --- a/Core/include/Acts/Geometry/Portal.hpp +++ b/Core/include/Acts/Geometry/Portal.hpp @@ -110,6 +110,7 @@ class Portal { /// precision). The resulting portal will have one portal along the shared /// surface's normal vector, and one opposite that vector. /// + /// ``` /// portal1 portal2 /// +---+ +---+ /// | | | | @@ -118,6 +119,7 @@ class Portal { /// | | | | /// | | | | /// +---+ +---+ + /// ``` /// /// @note The input portals need to have compatible link loadaout, e.g. one /// portal needs to have the *along normal* slot filled, and the @@ -140,6 +142,7 @@ class Portal { /// relative to one another (e.g. one along one opposite), the function will /// throw an exception. /// + /// ``` /// ^ ^ /// | | /// portal1| portal2| @@ -149,6 +152,7 @@ class Portal { /// | | /// | | /// v v + /// ``` /// /// @note This is a destructive operation on both portals, their /// links will be moved to produce merged links, which can fail From 43e6a1f95d96790c822bb0ede644db734928c057 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 3 Dec 2024 18:04:24 +0100 Subject: [PATCH 073/100] make toStream private, use `operator<<` on base class --- Core/include/Acts/Geometry/BlueprintNode.hpp | 9 +++++++-- Examples/Python/src/Blueprint.cpp | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index c0785c86d56..c12b66d8f53 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -40,8 +40,6 @@ class BlueprintNode { virtual const std::string& name() const = 0; - virtual void toStream(std::ostream& os) const; - virtual Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) = 0; @@ -97,7 +95,14 @@ class BlueprintNode { void graphViz(std::ostream& os) const; virtual void addToGraphviz(std::ostream& os) const; + friend std::ostream& operator<<(std::ostream& os, const BlueprintNode& node) { + node.toStream(os); + return os; + } + protected: + virtual void toStream(std::ostream& os) const; + std::string prefix() const; std::string indent() const; diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index d0a35d06f85..db39c4b261d 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -243,7 +243,7 @@ void addBlueprint(Context& ctx) { .def("__str__", [](const BlueprintNode& self) { std::stringstream ss; - self.toStream(ss); + ss << self; return ss.str(); }) .def("addChild", &BlueprintNode::addChild) From f88a5fc8b1500bab214558b3dfe5a1b96c74a977 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 3 Dec 2024 18:04:37 +0100 Subject: [PATCH 074/100] change Root node name --- Core/src/Geometry/Blueprint.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/Geometry/Blueprint.cpp b/Core/src/Geometry/Blueprint.cpp index 0d7817aebba..33daee6734b 100644 --- a/Core/src/Geometry/Blueprint.cpp +++ b/Core/src/Geometry/Blueprint.cpp @@ -21,7 +21,7 @@ namespace Acts { Blueprint::Blueprint(const Config &config) : m_cfg(config) {} const std::string &Blueprint::name() const { - static const std::string root = "root"; + static const std::string root = "Root"; return root; } From e9a28fed91cb896db445074b7229a4df7110bf7f Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 3 Dec 2024 18:05:16 +0100 Subject: [PATCH 075/100] doc strings part 1 --- Core/include/Acts/Geometry/Blueprint.hpp | 56 +++++++++++++- Core/include/Acts/Geometry/BlueprintNode.hpp | 75 ++++++++++++++++++- .../Acts/Geometry/StaticBlueprintNode.hpp | 17 +++++ 3 files changed, 143 insertions(+), 5 deletions(-) diff --git a/Core/include/Acts/Geometry/Blueprint.hpp b/Core/include/Acts/Geometry/Blueprint.hpp index ceedffbd775..e5541915a2e 100644 --- a/Core/include/Acts/Geometry/Blueprint.hpp +++ b/Core/include/Acts/Geometry/Blueprint.hpp @@ -17,8 +17,41 @@ namespace Acts { class GeometryContext; +/// This class is the top-level entry point to build a tracking geometry using +/// the blueprint building mechanism. It forms the root of a tree of nodes where +/// each node performs a portion of the construction. This top-level class has +/// the main construction methods that execute the construction of the geometry. +/// +/// ``` +/// +---------------+ +-----------+ +/// | | | | +/// | Root | | v +/// | | | +---------------+ +/// +---------------+ | | | +/// | | | Child 1 | +/// +----------+ | | | +/// v +----------+ +---------------+ +/// +---------------+ | +/// | | +--------------+ +/// | Child 2 | v +----------+ +/// | | .---------. | | +/// +---------------+ / \ | v +/// ( Proc node ) | +---------------+ +/// `. ,' | | | +/// `-------' | | Child 3 | +/// | | | | +/// | | +---------------+ +/// +---------+ +/// ``` +/// +/// The construction phases are documented in @c BlueprintNode, which is the +/// base class for all nodes in the tree. +/// @note This class inherits from @c BlueprintNode privately, because it is +/// only ever intented to be the top-level node, and not anywhere else in +/// the tree. class Blueprint : private BlueprintNode { public: + // Pull in convenience methods, despite privately inheriting using BlueprintNode::addChild; using BlueprintNode::addCylinderContainer; using BlueprintNode::addLayer; @@ -28,19 +61,34 @@ class Blueprint : private BlueprintNode { using BlueprintNode::graphViz; struct Config { + /// Determine how much envelope space to produce from the highest volume + /// in the geometry hierarchy and the world volume. ExtentEnvelope envelope = ExtentEnvelope::Zero(); + + /// The geometry identifier hook, passed through the `TrackingGeometry` + /// constructor. This will be superceded by a more integrated approach to + /// the identification scheme GeometryIdentifierHook geometryIdentifierHook = {}; }; - Blueprint(const Config& cfg); - - const std::string& name() const override; + /// Constructor from a config object + /// @param config The configuration object + Blueprint(const Config& config); + /// Construct the tracking geometry from the blueprint tree + /// @param options The construction options, see @c BlueprintOptions + /// @param gctx The geometry context for construction. In almost all cases, + /// this should be the *nominal* geometry context + /// @param logger The logger to use for output during construction std::unique_ptr construct( - const Options& options, const GeometryContext& gctx, + const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()); protected: + /// The name of the blueprint node, always "Root" + /// @return The name + const std::string& name() const override; + Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index c12b66d8f53..c3529adaea1 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -32,22 +32,96 @@ class MaterialDesignatorBlueprintNode; class StaticBlueprintNode; class LayerBlueprintNode; +/// Base class for all nodes in the blueprint tree. This class defines the +/// three-phase construction process. The three phases are +/// +/// -# **Build**: Construct volume representation + compute final sizing +/// -# **Connect**: Create and connect portals at volume boundaries +/// -# **Finalize**: Register portals with volumes + create acceleration +/// structures +/// +/// During the *build* phase, the `build` method of all nodes in the tree are +/// called recursively. Some nodes, like @c CylinderContainerBlueprintNode, +/// will take action on the volumes returns from its children, and perform +/// sizing to connect them. See the @c CylinderContainerBlueprintNode and @c +/// CylinderVolumeStack documentation for details on how the sizing is carried +/// out. class BlueprintNode { public: + /// Can be default constructed BlueprintNode() = default; + /// Virtual destructor to ensure correct cleanup virtual ~BlueprintNode() = default; + /// Get the name of this node virtual const std::string& name() const = 0; + /// This method is called during the *build* phase of the blueprint tree + /// construction. It returns a single @c Volume which represents transform + /// and bounds of the entire subtree. This does not have to correspond to the + /// final @c TrackingVolume, some node types will produce temporary volume + /// representations. Lifetime of the returned volume is managed by the source + /// node! + /// Nodes higher in the hierarchy will issue resizes down the tree hierarchy. + /// This is not done through a direct hierarchy, but coordinated by the + /// respective node type, by internally consulting its children. + /// + /// @note Generally, you should not need to to call this method directly. + /// The construction should usually be done through the special + /// @c Blueprint class. + /// + /// @param options The global construction options + /// @param gctx The geometry context for construction (usually nominal) + /// @param logger The logger to use for output during construction + /// @return The volume used for communicating transform and size up the hierarchy virtual Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) = 0; + /// This method is called during the *connect* phase. This phase handles the + /// creation and connection of *portals* (instances of @c PortalLinkBase). + /// After the build-phase has completed, the volume sizes are **final**. Each + /// node will consult its fully sized volume to produce *boundary surfaces*. + /// Each boundary surface is then turned into a @c TrivialPortalLink, which + /// in turn produces a one-sided portal (see @c Portal documentation) + /// + /// Some nodes (like @c CylinderContainerBlueprintNode) will take action on + /// their children, and unify the connected portals. + /// + /// After a node's processing has completed, it returns a reference to a @c + /// PortalShellBase, which represents a set of portals in a specific geometry + /// arrangement. The returned object lifetime is managed by the returning + /// node. + /// + /// @param options The global construction options + /// @param gctx The geometry context for construction (usually nominal) + /// @param logger The logger to use for output during construction virtual PortalShellBase& connect( const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) = 0; + /// This method is called during the *finalize* phase. This phase handles: + /// + /// - Registering portals into their final volumes + /// - Registering volumes into their parents + /// - Creating navigation policies + /// - (In future) Handle geometry identification assignment + /// + /// At the end of this phase, each node will have transfered any temporary + /// resources created during the build, that need to be retained, into the + /// final @c TrackingGeometry, and can be safely destroyed. + /// + /// @note The parent for volumes, portals, etc to be registered in is passed in as an + /// argument, rather than being implicitly determined from the **parent + /// node**. This is done so that nodes can remove themselves from the + /// final volume hierarchy, like container nodes or the + /// @c MaterialDesignatorBlueprintNode. + /// + /// @param options The global construction options + /// @param gctx The geometry context for construction (usually nominal) + /// @param parent The parent volume to register in + /// @param logger The logger to use for output during construction virtual void finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) = 0; @@ -110,5 +184,4 @@ class BlueprintNode { std::size_t m_depth{0}; std::vector> m_children{}; }; - }; // namespace Acts diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index ec57d0d2dad..b6952b418d2 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -15,20 +15,37 @@ namespace Acts { +/// The static blueprint node wraps a single already-constructred @c TrackingVolume. +/// The node will present this volume to its hierarchy. The volume is given as +/// mutable, and will be potentially enlarged in order to connect to neighboring +/// volumes. +/// - In case the volume already has child volumes, they will be retained. +/// - In case the volume already has a registered navigation policy, it will be +/// overwritten with the one configured on this node, regardless of content. class StaticBlueprintNode : public BlueprintNode { public: + /// Construct the static node from an existing volume + /// @param volume The volume to wrap StaticBlueprintNode(std::unique_ptr volume); + /// Get the name of this node. It is automatically taken from the wrapped + /// volume + /// @return The name of the volume const std::string& name() const override; + /// @copydoc BlueprintNode::build + /// Build-phase of the blueprint construction. Returns the wrapped volume for + /// sizing. Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; + /// @copydoc BlueprintNode::connect PortalShellBase& connect( const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; + /// @copydoc BlueprintNode::finalize void finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override; From 9b02b8c3772d894e2eb24755abc53c64903b7b6e Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Thu, 5 Dec 2024 16:53:13 +0100 Subject: [PATCH 076/100] docs: Misc docs fixes --- Core/include/Acts/Material/ProtoVolumeMaterial.hpp | 3 +-- Core/include/Acts/Seeding/PathSeeder.hpp | 2 -- Core/include/Acts/Utilities/Delegate.hpp | 9 ++++++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Core/include/Acts/Material/ProtoVolumeMaterial.hpp b/Core/include/Acts/Material/ProtoVolumeMaterial.hpp index 38206e8f6dc..dd302e31ccb 100644 --- a/Core/include/Acts/Material/ProtoVolumeMaterial.hpp +++ b/Core/include/Acts/Material/ProtoVolumeMaterial.hpp @@ -72,12 +72,11 @@ class ProtoVolumeMaterial : public IVolumeMaterial { Material m_material; }; -/// Return the material inline const Acts::Material Acts::ProtoVolumeMaterial::material( const Acts::Vector3& /*position*/) const { return m_material; } -/// Return the bin Utility + inline const Acts::BinUtility& Acts::ProtoVolumeMaterial::binUtility() const { return m_binUtility; } diff --git a/Core/include/Acts/Seeding/PathSeeder.hpp b/Core/include/Acts/Seeding/PathSeeder.hpp index 87ceda365c8..f619f1a0ab4 100644 --- a/Core/include/Acts/Seeding/PathSeeder.hpp +++ b/Core/include/Acts/Seeding/PathSeeder.hpp @@ -108,8 +108,6 @@ class PathSeeder { /// @param gctx The geometry context /// @param sourceLinkGridLookup The lookup table for the source links /// @param seedCollection The collection of seeds to fill - /// - /// @return The vector of seeds template void findSeeds(const GeometryContext& gctx, const std::unordered_map& diff --git a/Core/include/Acts/Utilities/Delegate.hpp b/Core/include/Acts/Utilities/Delegate.hpp index a0ef2cf7252..8cac473abb9 100644 --- a/Core/include/Acts/Utilities/Delegate.hpp +++ b/Core/include/Acts/Utilities/Delegate.hpp @@ -50,7 +50,6 @@ class Delegate { /// Alias of the return type using return_type = R; using holder_type = H; - /// Alias to the function pointer type this class will store using function_type = return_type (*)(const holder_type *, Args...); using function_ptr_type = return_type (*)(Args...); using signature_type = R(Args...); @@ -81,12 +80,14 @@ class Delegate { Delegate(const Delegate &) noexcept = default; Delegate &operator=(const Delegate &) noexcept = default; + /// @cond /// Constructor with an explicit runtime callable /// @param callable The runtime value of the callable /// @note The function signature requires the first argument of the callable is `const void*`. /// i.e. if the signature of the delegate is `void(int)`, the /// callable's signature has to be `void(const void*, int)`. explicit Delegate(function_type callable) { connect(callable); } + /// @endcond /// Constructor with a possibly stateful function object. /// @tparam Callable Type of the callable @@ -129,6 +130,7 @@ class Delegate { requires(isNoFunPtr::value) = delete; + /// @cond /// Assignment operator with an explicit runtime callable /// @param callable The runtime value of the callable /// @note The function signature requires the first argument of the callable is `const void*`. @@ -147,6 +149,7 @@ class Delegate { { connect(callable); } + /// @endcond /// Assignment operator from rvalue reference is deleted, should catch /// assignment from temporary objects and thus invalid pointers @@ -155,6 +158,7 @@ class Delegate { requires(isNoFunPtr::value) = delete; + /// @cond /// Connect a free function pointer. /// @note The function pointer must be ``constexpr`` for @c Delegate to accept it /// @tparam Callable The compile-time free function pointer @@ -175,6 +179,7 @@ class Delegate { return std::invoke(Callable, std::forward(args)...); }; } + /// @endcond /// Assignment operator with possibly stateful function object. /// @tparam Callable Type of the callable @@ -195,6 +200,7 @@ class Delegate { requires(isNoFunPtr::value) = delete; + /// @cond /// Connect anything that is assignable to the function pointer /// @param callable The runtime value of the callable /// @note The function signature requires the first argument of the callable is `const void*`. @@ -206,6 +212,7 @@ class Delegate { } m_function = callable; } + /// @endcond template void connect(function_type callable, const Type *instance) From f4e5717e560873935cd0241ff1715e6d048327d5 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Thu, 5 Dec 2024 18:23:25 +0100 Subject: [PATCH 077/100] API cleanup, remove unneeded methods, move definition to cpp --- .../CylinderContainerBlueprintNode.hpp | 13 ++++--------- .../Acts/Geometry/LayerBlueprintNode.hpp | 10 ---------- .../MaterialDesignatorBlueprintNode.hpp | 15 ++------------- .../CylinderContainerBlueprintNode.cpp | 15 ++++++++++++++- Core/src/Geometry/LayerBlueprintNode.cpp | 18 ------------------ .../MaterialDesignatorBlueprintNode.cpp | 17 +++++++++++++++++ Examples/Python/src/Blueprint.cpp | 2 -- 7 files changed, 37 insertions(+), 53 deletions(-) diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index 6857a5a26bb..c37a0aca8c5 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -29,8 +29,6 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { const std::string& name() const override; - void setName(const std::string& name) { m_name = name; } - Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; @@ -47,13 +45,10 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { CylinderContainerBlueprintNode& setResizeStrategy( CylinderVolumeStack::ResizeStrategy resizeStrategy); - BinningValue direction() const { return m_direction; } - CylinderVolumeStack::AttachmentStrategy attachmentStrategy() const { - return m_attachmentStrategy; - } - CylinderVolumeStack::ResizeStrategy resizeStrategy() const { - return m_resizeStrategy; - } + BinningValue direction() const; + + CylinderVolumeStack::AttachmentStrategy attachmentStrategy() const; + CylinderVolumeStack::ResizeStrategy resizeStrategy() const; private: void addToGraphviz(std::ostream& os) const override; diff --git a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp index 1dbe03e20be..67d5d98bfcc 100644 --- a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp @@ -26,10 +26,6 @@ class LayerBlueprintNode : public StaticBlueprintNode { Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; - void finalize(const BlueprintOptions& options, const GeometryContext& gctx, - TrackingVolume& parent, - const Logger& logger = Acts::getDummyLogger()) override; - LayerBlueprintNode& setSurfaces( std::vector> surfaces); @@ -47,12 +43,6 @@ class LayerBlueprintNode : public StaticBlueprintNode { const LayerType& layerType() const; - LayerBlueprintNode& setNavigationPolicyFactory( - std::shared_ptr navigationPolicyFactory) - override; - - const NavigationPolicyFactory* navigationPolicyFactory() const; - void addToGraphviz(std::ostream& os) const override; private: diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index 7d5c5a79bbf..8b10dc32318 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -12,7 +12,6 @@ #include "Acts/Geometry/BlueprintNode.hpp" #include "Acts/Geometry/PortalShell.hpp" -#include #include namespace Acts { @@ -43,19 +42,9 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { void addToGraphviz(std::ostream& os) const override; - const std::optional& binning() { return m_binning; } + const std::optional& binning() const; - MaterialDesignatorBlueprintNode& setBinning(BinningConfig binning) { - m_binning = std::move(binning); - return *this; - } - - const std::string& getName() const { return m_name; } - - MaterialDesignatorBlueprintNode& setName(std::string name) { - m_name = std::move(name); - return *this; - } + MaterialDesignatorBlueprintNode& setBinning(BinningConfig binning); private: std::string m_name{}; diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index a0dce32f89a..aa5c706ee44 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -162,7 +162,6 @@ void CylinderContainerBlueprintNode::finalize(const BlueprintOptions& options, throw std::runtime_error("Volume is not connected"); } - // @TODO: Add ability to override this const auto* policyFactory = options.defaultNavigationPolicyFactory.get(); ACTS_DEBUG(prefix() << "Registering " << m_gaps.size() @@ -232,4 +231,18 @@ void CylinderContainerBlueprintNode::addToGraphviz(std::ostream& os) const { } } +BinningValue CylinderContainerBlueprintNode::direction() const { + return m_direction; +} + +CylinderVolumeStack::AttachmentStrategy +CylinderContainerBlueprintNode::attachmentStrategy() const { + return m_attachmentStrategy; +} + +CylinderVolumeStack::ResizeStrategy +CylinderContainerBlueprintNode::resizeStrategy() const { + return m_resizeStrategy; +} + } // namespace Acts diff --git a/Core/src/Geometry/LayerBlueprintNode.cpp b/Core/src/Geometry/LayerBlueprintNode.cpp index 2dd67faf7d9..ce6f1208439 100644 --- a/Core/src/Geometry/LayerBlueprintNode.cpp +++ b/Core/src/Geometry/LayerBlueprintNode.cpp @@ -88,13 +88,6 @@ void LayerBlueprintNode::buildVolume(const Extent& extent, std::make_unique(transform, std::move(bounds), m_name); } -void LayerBlueprintNode::finalize(const BlueprintOptions& options, - const GeometryContext& gctx, - TrackingVolume& parent, - const Logger& logger) { - StaticBlueprintNode::finalize(options, gctx, parent, logger); -} - const std::string& LayerBlueprintNode::name() const { return m_name; } @@ -139,17 +132,6 @@ const LayerBlueprintNode::LayerType& LayerBlueprintNode::layerType() const { return m_layerType; } -LayerBlueprintNode& LayerBlueprintNode::setNavigationPolicyFactory( - std::shared_ptr navigationPolicyFactory) { - m_navigationPolicyFactory = std::move(navigationPolicyFactory); - return *this; -} - -const NavigationPolicyFactory* LayerBlueprintNode::navigationPolicyFactory() - const { - return m_navigationPolicyFactory.get(); -} - void LayerBlueprintNode::addToGraphviz(std::ostream& os) const { std::stringstream ss; ss << "" << name() << ""; diff --git a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp index 465fb8c0821..5c1f1218010 100644 --- a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp +++ b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp @@ -36,6 +36,12 @@ Volume& MaterialDesignatorBlueprintNode::build(const BlueprintOptions& options, throw std::runtime_error( "MaterialDesignatorBlueprintNode must have exactly one child"); } + + if (!m_binning) { + ACTS_ERROR(prefix() << "Binning is not set"); + throw std::runtime_error("Binning is not set"); + } + return children().at(0).build(options, gctx, logger); } @@ -164,4 +170,15 @@ void MaterialDesignatorBlueprintNode::addToGraphviz(std::ostream& os) const { BlueprintNode::addToGraphviz(os); } +const std::optional& +MaterialDesignatorBlueprintNode::binning() const { + return m_binning; +} + +MaterialDesignatorBlueprintNode& MaterialDesignatorBlueprintNode::setBinning( + BinningConfig binning) { + m_binning = std::move(binning); + return *this; +} + } // namespace Acts diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index db39c4b261d..4f2a865bdbe 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -378,8 +378,6 @@ void addBlueprint(Context& ctx) { std::shared_ptr>( m, "MaterialDesignatorBlueprintNode") .def(py::init(), "name"_a) - .def_property("name", &MaterialDesignatorBlueprintNode::name, - &MaterialDesignatorBlueprintNode::setName) .def_property("binning", &MaterialDesignatorBlueprintNode::binning, &MaterialDesignatorBlueprintNode::setBinning); From ca1c08afa1b031050856cc8f8eebac4b14c74335 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Thu, 5 Dec 2024 18:23:57 +0100 Subject: [PATCH 078/100] doc strings part 2 --- Core/include/Acts/Geometry/Blueprint.hpp | 4 + Core/include/Acts/Geometry/BlueprintNode.hpp | 152 +++++++++++++++--- .../CylinderContainerBlueprintNode.hpp | 78 ++++++++- .../Acts/Geometry/LayerBlueprintNode.hpp | 68 +++++++- .../MaterialDesignatorBlueprintNode.hpp | 36 +++++ 5 files changed, 314 insertions(+), 24 deletions(-) diff --git a/Core/include/Acts/Geometry/Blueprint.hpp b/Core/include/Acts/Geometry/Blueprint.hpp index e5541915a2e..dc700a2488b 100644 --- a/Core/include/Acts/Geometry/Blueprint.hpp +++ b/Core/include/Acts/Geometry/Blueprint.hpp @@ -89,17 +89,21 @@ class Blueprint : private BlueprintNode { /// @return The name const std::string& name() const override; + /// @copydoc BlueprintNode::build Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; + /// @copydoc BlueprintNode::connect PortalShellBase& connect( const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; + /// @copydoc BlueprintNode::finalize void finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) override; + /// @copydoc BlueprintNode::addToGraphviz void addToGraphviz(std::ostream& os) const override; private: diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index c3529adaea1..74dcec91b92 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -41,11 +41,11 @@ class LayerBlueprintNode; /// structures /// /// During the *build* phase, the `build` method of all nodes in the tree are -/// called recursively. Some nodes, like @c CylinderContainerBlueprintNode, +/// called recursively. Some nodes, like @ref Acts::CylinderContainerBlueprintNode, /// will take action on the volumes returns from its children, and perform -/// sizing to connect them. See the @c CylinderContainerBlueprintNode and @c -/// CylinderVolumeStack documentation for details on how the sizing is carried -/// out. +/// sizing to connect them. See the @ref Acts::CylinderContainerBlueprintNode and @ref +/// Acts::CylinderVolumeStack documentation for details on how the sizing is +/// carried out. class BlueprintNode { public: /// Can be default constructed @@ -57,10 +57,16 @@ class BlueprintNode { /// Get the name of this node virtual const std::string& name() const = 0; + /// @anchor construction + /// @name Construction methods + /// These methods constitute the primary interface of the node that + /// participates in the geometry construction. + /// @{ + /// This method is called during the *build* phase of the blueprint tree - /// construction. It returns a single @c Volume which represents transform + /// construction. It returns a single @ref Acts::Volume which represents transform /// and bounds of the entire subtree. This does not have to correspond to the - /// final @c TrackingVolume, some node types will produce temporary volume + /// final @ref Acts::TrackingVolume, some node types will produce temporary volume /// representations. Lifetime of the returned volume is managed by the source /// node! /// Nodes higher in the hierarchy will issue resizes down the tree hierarchy. @@ -69,7 +75,7 @@ class BlueprintNode { /// /// @note Generally, you should not need to to call this method directly. /// The construction should usually be done through the special - /// @c Blueprint class. + /// @ref Acts::Blueprint class. /// /// @param options The global construction options /// @param gctx The geometry context for construction (usually nominal) @@ -80,19 +86,19 @@ class BlueprintNode { const Logger& logger = Acts::getDummyLogger()) = 0; /// This method is called during the *connect* phase. This phase handles the - /// creation and connection of *portals* (instances of @c PortalLinkBase). + /// creation and connection of *portals* (instances of @ref Acts::PortalLinkBase). /// After the build-phase has completed, the volume sizes are **final**. Each /// node will consult its fully sized volume to produce *boundary surfaces*. - /// Each boundary surface is then turned into a @c TrivialPortalLink, which - /// in turn produces a one-sided portal (see @c Portal documentation) + /// Each boundary surface is then turned into a @ref Acts::TrivialPortalLink, which + /// in turn produces a one-sided portal (see @ref Acts::Portal documentation) /// - /// Some nodes (like @c CylinderContainerBlueprintNode) will take action on + /// Some nodes (like @ref Acts::CylinderContainerBlueprintNode) will take action on /// their children, and unify the connected portals. /// - /// After a node's processing has completed, it returns a reference to a @c - /// PortalShellBase, which represents a set of portals in a specific geometry - /// arrangement. The returned object lifetime is managed by the returning - /// node. + /// After a node's processing has completed, it returns a reference to a @ref + /// Acts::PortalShellBase, which represents a set of portals in a specific + /// geometry arrangement. The returned object lifetime is managed by the + /// returning node. /// /// @param options The global construction options /// @param gctx The geometry context for construction (usually nominal) @@ -110,13 +116,13 @@ class BlueprintNode { /// /// At the end of this phase, each node will have transfered any temporary /// resources created during the build, that need to be retained, into the - /// final @c TrackingGeometry, and can be safely destroyed. + /// final @ref Acts::TrackingGeometry, and can be safely destroyed. /// - /// @note The parent for volumes, portals, etc to be registered in is passed in as an - /// argument, rather than being implicitly determined from the **parent - /// node**. This is done so that nodes can remove themselves from the - /// final volume hierarchy, like container nodes or the - /// @c MaterialDesignatorBlueprintNode. + /// @note The @p parent for volumes, portals, etc to be registered in is passed in **as an + /// argument**, rather than being implicitly determined from the + /// **parent node**. This is done so that nodes can remove themselves + /// from the final volume hierarchy, like container nodes or the + /// @ref Acts::MaterialDesignatorBlueprintNode. /// /// @param options The global construction options /// @param gctx The geometry context for construction (usually nominal) @@ -126,58 +132,162 @@ class BlueprintNode { const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger = Acts::getDummyLogger()) = 0; + /// @} + + /// @anchor convenience + /// @name Convenience methods + /// These methods are meant to make the construction of a blueprint tree in + /// code more ergonomic. + /// They usually take an optional `callback` paramater. The primary use for + /// this parameter is structural, as it facilitates introducing scopes to + /// indicate in code that objects are nested. + /// + /// ```cpp + /// Blueprint::Config cfg; + /// auto root = std::make_unique(cfg); + /// root->addStaticVolume( + /// base, std::make_shared(50_mm, 400_mm, 1000_mm), + /// "PixelWrapper", [&](auto& wrapper) { + /// // This scope can be used to equip `wrapper` + /// }); + /// ``` + /// + /// Alternatively, they can also be used without a callback, as the newly + /// created node is also returned by reference: + /// + /// ``` + /// auto& wrapper = root->addStaticVolume( + /// base, std::make_shared(50_mm, 400_mm, 1000_mm), + /// "PixelWrapper"); + /// ``` + /// + /// In both cases, it's not necessary to register the newly created node + /// with a parent node. + /// + /// @{ + + /// This method creates a new @ref Acts::StaticBlueprintNode wrapping @p + /// volume and adds it to this node as a child. + /// @param volume The volume to add + /// @param callback An optional callback that receives the node as an argument + /// @return A reference to the created node StaticBlueprintNode& addStaticVolume( std::unique_ptr volume, const std::function& callback = {}); + /// Alternative overload for creating a @ref Acts::StaticBlueprintNode. This + /// overload will invoke the constructor of @ref Acts::TrackingVolume and use + /// that volume to create the node. + /// @param transform The transform of the volume + /// @param volbounds The bounds of the volume + /// @param volumeName The name of the volume + /// @param callback An optional callback that receives the node as an argument StaticBlueprintNode& addStaticVolume( const Transform3& transform, std::shared_ptr volbounds, const std::string& volumeName = "undefined", const std::function& callback = {}); + /// Convenience method for creating a @ref Acts::CylinderContainerBlueprintNode. + /// @param name The name of the container node. This name is only reflected + /// in the node tree for debugging, as no extra volumes is created + /// for the container. + /// @param direction The direction of the stack configuration. See + /// @ref Acts::CylinderVolumeStack for details. + /// @param callback An optional callback that receives the node as an argument CylinderContainerBlueprintNode& addCylinderContainer( const std::string& name, BinningValue direction, const std::function& callback = {}); + /// Convenience method for creating a @ref Acts::MaterialDesignatorBlueprintNode. + /// @param name The name of the material designator node. Used for debugging + /// the node tree only. + /// @param callback An optional callback that receives the node as an argument MaterialDesignatorBlueprintNode& addMaterial( const std::string& name, const std::function& callback = {}); + /// Convenience method for creating a @ref Acts::LayerBlueprintNode. + /// @param name The name of the layer node. + /// @param callback An optional callback that receives the node as an argument LayerBlueprintNode& addLayer( const std::string& name, const std::function& callback = {}); + /// @} + + /// Register a @p child to this node. + /// @warning This method throws if adding the child would create a + /// cycle in the blueprint tree! + /// @param child The child node to add + /// @return A reference this node (not the child!) BlueprintNode& addChild(std::shared_ptr child); + /// A range-like object that allows range based for loops and index access. + /// This type's iterators and accessors return mutable references when + /// dereferenced. using MutableChildRange = detail::TransformRange>>; + /// A range-like object that allows range based for loops and index access. + /// This type's iterators and accessors return const references when + /// dereferenced. using ChildRange = detail::TransformRange>>; + /// Return a @ref MutableChildRange to the children of this node. + /// @return A range-like object to the children MutableChildRange children(); + + /// Return a @ref ChildRange to the children of this node. + /// @return A range-like object to the children ChildRange children() const; + /// Remove all children from this node void clearChildren(); + /// Return the depth of this node in the blueprint tree. A depth of zero means + /// this node does not have a parent. + /// @return The depth of this node std::size_t depth() const; + /// Print the node tree starting from this node to graphviz format + /// @param os The stream to print to void graphViz(std::ostream& os) const; + + /// Method that writes a representatiohn of **this node only** to graphviz. + /// This should generally not be called on its own, but through the @ref + /// BlueprintNode::graphViz method. + /// @param os The stream to print to virtual void addToGraphviz(std::ostream& os) const; + /// Print a representation of this node to the stream + /// @param os The stream to print to + /// @param node The node to print + /// @return The output stream friend std::ostream& operator<<(std::ostream& os, const BlueprintNode& node) { node.toStream(os); return os; } protected: + /// Virtual method to determine stream representation. + /// @note This method is called by the stream operator. virtual void toStream(std::ostream& os) const; + /// Increase the depth of this node and all descendents by one. + void incrementDepth(); + + /// Printing helper returning a prefix including an indent depending on the + /// depth. + /// @return The prefix string std::string prefix() const; + + /// An indentation depending on the depth of this node. + /// @return The indentation string std::string indent() const; private: diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index c37a0aca8c5..e218d3c207b 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -18,8 +18,23 @@ namespace Acts { +/// This class handles the case of wrapping a set of cylinder-shaped children +/// and stacking them in a configured direction. +/// The stacking is done using @ref CylinderVolumeStack. +/// The container does not result in an extra volume in the hierarchy, as all +/// input volumes and any gap volumes produced are directly registered in the +/// volume of the parent of this node. +/// @note This node assumes all children produce only cylinder volumes! It throws +/// if this is not the case. class CylinderContainerBlueprintNode final : public BlueprintNode { public: + /// Main constructor for t he cylinder container node. + /// @param name The name of the node (for debug only) + /// @param direction The stacking direction + /// @param attachmentStrategy The attachment strategy for the stack + /// @param resizeStrategy The resize strategy + /// @note The parameters are passed through to @ref CylinderVolumeStack, + /// see documentation of that class for more information CylinderContainerBlueprintNode( const std::string& name, BinningValue direction, CylinderVolumeStack::AttachmentStrategy attachmentStrategy = @@ -27,49 +42,108 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { CylinderVolumeStack::ResizeStrategy resizeStrategy = CylinderVolumeStack::ResizeStrategy::Expand); + /// @copydoc BlueprintNode::name const std::string& name() const override; + /// This participates in the construction of the geometry via the blueprint + /// tree. The steps are approximately as follows: + /// -# Collect all child volumes + /// -# Package them into a @ref Acts::CylinderVolumeStack, which performs sizing and/or gap cration + /// -# Return the @ref Acts::CylinderVolumeStack as a volume up the tree + /// + /// @param options The global blueprint options + /// @param gctx The geometry context (nominal usually) + /// @param logger The logger to use + /// @return The combined @ref Acts::CylinderVolumeStack Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; + /// This participates in the construction of the geometry via the blueprint + /// tree. The steps are approximately as follows: + /// -# Walk through all volumes that were created by the build phase + /// -# Check if they are: *real* child volumes or gap volumes + /// - If gap volume: produce a @ref Acts::TrackingVolume, and wrap it in a single use shell + /// - If child volume: locate the right child node it came from, call + /// ` connect` and collect the returned shell + /// -# Produce a combined @ref Acts::CylinderStackPortalShell from all the shells + /// -# Return that shell representation + /// + /// @param options The global blueprint options + /// @param gctx The geometry context (nominal usually) + /// @param logger The logger to use + /// @return The combined @ref Acts::CylinderStackPortalShell CylinderStackPortalShell& connect( const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; + /// This participates in the construction of the geometry via the blueprint + /// tree. The steps are approximately as follows: + /// -# Register portals created for gap volumes, as they're not handled by + /// dedicated nodes + /// -# Register gap volumes in the @p parent volume + /// -# Create a configured @ref Acts::NavigationPolicy for the gap + /// -# Call `finalize` on all children while passing through @p parent. + /// + /// @param options The global blueprint options + /// @param gctx The geometry context (nominal usually) + /// @param parent The parent volume + /// @param logger The logger to use void finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) override; + /// Setter for the stacking direction + /// @param direction The stacking direction + /// @return This node for chaining CylinderContainerBlueprintNode& setDirection(BinningValue direction); + + /// Setter for the attachment strategy + /// @param attachmentStrategy The attachment strategy + /// @return This node for chaining CylinderContainerBlueprintNode& setAttachmentStrategy( CylinderVolumeStack::AttachmentStrategy attachmentStrategy); + + /// Setter for the resize strategy + /// @param resizeStrategy The resize strategy + /// @return This node for chaining CylinderContainerBlueprintNode& setResizeStrategy( CylinderVolumeStack::ResizeStrategy resizeStrategy); + /// Accessor to the stacking direction + /// @return The stacking direction BinningValue direction() const; + /// Accessor to the attachment strategy + /// @return The attachment strategy CylinderVolumeStack::AttachmentStrategy attachmentStrategy() const; + + /// Accessor to the resize strategy + /// @return The resize strategy CylinderVolumeStack::ResizeStrategy resizeStrategy() const; private: + /// @copydoc BlueprintNode::addToGraphviz void addToGraphviz(std::ostream& os) const override; + /// Helper function to check if a volume was created as a gap volume. + /// @param volume The volume to check + /// @return True if the volume is a gap volume, false otherwise bool isGapVolume(const Volume& volume) const; std::string m_name; BinningValue m_direction; + CylinderVolumeStack::AttachmentStrategy m_attachmentStrategy; + CylinderVolumeStack::ResizeStrategy m_resizeStrategy; // Is only initialized during `build` std::vector m_childVolumes; std::unique_ptr m_stack{nullptr}; std::map m_volumeToNode; - std::vector, std::unique_ptr>> m_gaps; - std::unique_ptr m_shell{nullptr}; }; diff --git a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp index 67d5d98bfcc..63c28048bdf 100644 --- a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp @@ -14,38 +14,101 @@ namespace Acts { +/// The layer node is essentially an auto-sizing wrapper around a set of +/// surfaces. +/// @note This implementation is **preliminary** and will likely change +/// in the future. +/// It defers most of the functionality to @ref Acts::StaticBlueprintNode, +/// after the initial volume creation is completed. +/// +/// The layer volume is created to wrap around the surfaces registered with +/// this node. The orientation of the resulting volume defaults to the identity +/// matrix. If another orientation is desired, this can be set with the @ref +/// Acts::LayerBlueprintNode::setTransform. See @ref Acts::ProtoLayer for +/// details on the auto-sizing from surfaces. +/// class LayerBlueprintNode : public StaticBlueprintNode { public: - enum class LayerType { Cylinder, Disc, Plane }; + /// Enum that lists out the supported layer types. + enum class LayerType { + /// A cylinder layer + Cylinder, + /// A disc layer + Disc, + + /// A plane layer + /// @note This is not yet implemented + Plane + }; + + /// Constructor for a layer node. + /// @param name The name of the layer LayerBlueprintNode(const std::string& name) : StaticBlueprintNode{nullptr}, m_name(name) {} + /// @copydoc BlueprintNode::name const std::string& name() const override; + /// This function participates in the geometry construction. + /// It will: + /// -# Analyze the surfaces provided and produce a wrapping volume + /// -# Register the surfaces with the volume + /// -# Return the volume + /// @note At least one surfaces needs to be registered via + /// @ref Acts::LayerBlueprintNode::setSurfaces before + /// geometry construction. Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; + /// Register a set of surfaces with the layer node. + /// @param surfaces The surfaces to register + /// @return Reference to this node for chaining LayerBlueprintNode& setSurfaces( std::vector> surfaces); + /// Access the registered surfaces. + /// @return The registered surfaces const std::vector>& surfaces() const; + /// Set the transformation of the layer node. + /// This can be used to specifically orient the resulting layer volume. + /// @param transform The transformation to set + /// @return Reference to this node for chaining LayerBlueprintNode& setTransform(const Transform3& transform); + /// Access the transformation of the layer node. + /// @return The transformation const Transform3& transform() const; + /// Set the envelope of the layer node. This configures the amount of space to + /// add around the contained surfaces. + /// @param envelope The envelope to set + /// @return Reference to this node for chaining LayerBlueprintNode& setEnvelope(const ExtentEnvelope& envelope); + /// Access the envelope of the layer node. + /// @return The envelope const ExtentEnvelope& envelope() const; + /// Set the layer type of the layer node. + /// @param layerType The layer type to set + /// @return Reference to this node for chaining LayerBlueprintNode& setLayerType(LayerType layerType); + /// Access the layer type of the layer node. + /// @return The layer type const LayerType& layerType() const; + /// @copydoc Acts::BlueprintNode::addToGraphviz void addToGraphviz(std::ostream& os) const override; private: + /// Helper method that performs the volume creation from the configured + /// surfaces. It converts from an @p extent object to an instance of @ref + /// Acts::VolumeBounds. + /// @param extent The extent to use for the volume creation + /// @param logger The logger to use void buildVolume(const Extent& extent, const Logger& logger); std::string m_name; @@ -55,6 +118,9 @@ class LayerBlueprintNode : public StaticBlueprintNode { LayerType m_layerType = LayerType::Cylinder; }; +/// Output operator for the layer type enum. +/// @param os The output stream +/// @param type The layer type std::ostream& operator<<(std::ostream& os, LayerBlueprintNode::LayerType type); } // namespace Acts diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index 8b10dc32318..d30753c951b 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -16,6 +16,12 @@ namespace Acts { +/// This node type registers material proxies into its child volume during the +/// blueprint construction. It is configured ahead of time which volume faces to +/// mark up, and how do to so. +/// @note This node can only have a single child. This is not an error during +/// tree building, but during geometry constuction. +/// @note This currently only supports a cylinder volume child class MaterialDesignatorBlueprintNode final : public BlueprintNode { public: // @TODO: This needs cuboid volume storage as well @@ -24,26 +30,56 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { std::tuple>>; + /// Main constructor for the material designator node. + /// @param name The name of the node (for debug only) MaterialDesignatorBlueprintNode(const std::string& name) : m_name(name) {} + /// @copydoc BlueprintNode::name const std::string& name() const override; + /// @copydoc BlueprintNode::toStream void toStream(std::ostream& os) const override; + /// This method participates in the geometry construction. + /// It checks that this node only has a single child, is correctly configured, + /// and forwards the call. + /// @param options The global blueprint options + /// @param gctx The geometry context (nominal usually) + /// @param logger The logger to use + /// @return The child volume Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; + /// This method participates in the geometry construction. + /// It receives the populated portal shell from its only child and attaches + /// material proxies by consulting the configuration stored in the node. + /// @note Currently, this node will unconditionally attach + /// @ref Acrs::ProtoGridSurfaceMaterial + /// + /// @param options The global blueprint options + /// @param gctx The geometry context (nominal usually) + /// @param logger The logger to use PortalShellBase& connect( const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; + /// This method participates in the geometry construction. + /// Passes through the call to its only child. + /// @param options The global blueprint options + /// @param gctx The geometry context (nominal usually) + /// @param parent The parent volume void finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) override; + /// @copydoc BlueprintNode::addToGraphviz void addToGraphviz(std::ostream& os) const override; + /// Retrieve the binning configuration + /// @return The binning configuration const std::optional& binning() const; + /// Set the binning configuration + /// @param binning The binning configuration MaterialDesignatorBlueprintNode& setBinning(BinningConfig binning); private: From 35db2c5afd452a618578171228301fce0ec32907 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Thu, 5 Dec 2024 18:24:14 +0100 Subject: [PATCH 079/100] add extra checks for cycles + tests --- Core/src/Geometry/BlueprintNode.cpp | 38 ++++++++++- .../Core/Geometry/BlueprintTests.cpp | 68 +++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index 6c6561570c6..94a7a330552 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -19,12 +19,41 @@ namespace Acts { +namespace { +bool hasDescendent(const BlueprintNode& descendent, + const BlueprintNode& ancestor) { + if (&descendent == &ancestor) { + return true; + } + + for (const auto& child : ancestor.children()) { + if (hasDescendent(descendent, child)) { + return true; + } + } + + return false; +} +} // namespace + void BlueprintNode::toStream(std::ostream& os) const { os << "BlueprintNode(" << name() << ")"; } BlueprintNode& BlueprintNode::addChild(std::shared_ptr child) { - child->m_depth = m_depth + 1; + if (!child) { + throw std::invalid_argument("Child is nullptr"); + } + + if (child->depth() != 0) { + throw std::invalid_argument("Child has already been added to another node"); + } + + if (hasDescendent(*this, *child)) { + throw std::invalid_argument("Adding child would create a cycle"); + } + + child->incrementDepth(); m_children.push_back(std::move(child)); return *this; } @@ -41,6 +70,13 @@ std::size_t BlueprintNode::depth() const { return m_depth; } +void BlueprintNode::incrementDepth() { + m_depth++; + for (auto& child : m_children) { + child->incrementDepth(); + } +} + std::string BlueprintNode::indent() const { return std::string(m_depth * 2, ' '); } diff --git a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp index 542b6ea1a28..394ac3f05fe 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp @@ -13,6 +13,7 @@ #include "Acts/Definitions/Units.hpp" #include "Acts/Geometry/Blueprint.hpp" +#include "Acts/Geometry/BlueprintNode.hpp" #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/CylinderVolumeBounds.hpp" #include "Acts/Geometry/CylinderVolumeStack.hpp" @@ -90,6 +91,73 @@ BOOST_AUTO_TEST_CASE(InvalidRoot) { BOOST_CHECK_THROW(root.construct({}, gctx, *logger), std::logic_error); } +class DummyNode : public BlueprintNode { + public: + DummyNode(const std::string& name) : m_name(name) {} + + const std::string& name() const override { return m_name; } + + Volume& build(const BlueprintOptions& /*options*/, + const GeometryContext& /*gctx*/, + const Acts::Logger& /*logger*/) override { + throw std::logic_error("Not implemented"); + } + + PortalShellBase& connect(const BlueprintOptions& /*options*/, + const GeometryContext& /*gctx*/, + const Logger& /*logger */) override { + throw std::logic_error("Not implemented"); + } + + void finalize(const BlueprintOptions& /*options*/, + const GeometryContext& /*gctx*/, TrackingVolume& /*parent*/, + const Logger& /*logger*/) override { + throw std::logic_error("Not implemented"); + } + + private: + std::string m_name; +}; + +BOOST_AUTO_TEST_CASE(AddChildInvalid) { + auto node = std::make_shared("node"); + + // Add self + BOOST_CHECK_THROW(node->addChild(node), std::invalid_argument); + + // Add nullptr + BOOST_CHECK_THROW(node->addChild(nullptr), std::invalid_argument); + + auto nodeB = std::make_shared("nodeB"); + auto nodeC = std::make_shared("nodeC"); + + node->addChild(nodeB); + nodeB->addChild(nodeC); + BOOST_CHECK_THROW(nodeC->addChild(node), std::invalid_argument); + + // already has parent, can't be added as a child anywhere else + BOOST_CHECK_THROW(node->addChild(nodeC), std::invalid_argument); +} + +BOOST_AUTO_TEST_CASE(Depth) { + auto node1 = std::make_shared("node1"); + auto node2 = std::make_shared("node2"); + auto node3 = std::make_shared("node3"); + + BOOST_CHECK_EQUAL(node1->depth(), 0); + BOOST_CHECK_EQUAL(node2->depth(), 0); + BOOST_CHECK_EQUAL(node3->depth(), 0); + + node2->addChild(node3); + BOOST_CHECK_EQUAL(node2->depth(), 0); + BOOST_CHECK_EQUAL(node3->depth(), 1); + + node1->addChild(node2); + BOOST_CHECK_EQUAL(node1->depth(), 0); + BOOST_CHECK_EQUAL(node2->depth(), 1); + BOOST_CHECK_EQUAL(node3->depth(), 2); +} + BOOST_AUTO_TEST_CASE(Static) { Blueprint::Config cfg; cfg.envelope[BinningValue::binZ] = {20_mm, 20_mm}; From a480fdbebd4b7b105d56c7b7772738b85761f2b1 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 6 Dec 2024 09:49:44 +0100 Subject: [PATCH 080/100] visibility shuffling --- Core/include/Acts/Geometry/LayerBlueprintNode.hpp | 2 +- .../Acts/Geometry/MaterialDesignatorBlueprintNode.hpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp index 63c28048bdf..8ca3f3ca40e 100644 --- a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp @@ -100,10 +100,10 @@ class LayerBlueprintNode : public StaticBlueprintNode { /// @return The layer type const LayerType& layerType() const; + private: /// @copydoc Acts::BlueprintNode::addToGraphviz void addToGraphviz(std::ostream& os) const override; - private: /// Helper method that performs the volume creation from the configured /// surfaces. It converts from an @p extent object to an instance of @ref /// Acts::VolumeBounds. diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index d30753c951b..dfb6ac77b00 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -20,7 +20,7 @@ namespace Acts { /// blueprint construction. It is configured ahead of time which volume faces to /// mark up, and how do to so. /// @note This node can only have a single child. This is not an error during -/// tree building, but during geometry constuction. +/// tree building, but during geometry construction. /// @note This currently only supports a cylinder volume child class MaterialDesignatorBlueprintNode final : public BlueprintNode { public: @@ -71,9 +71,6 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { void finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) override; - /// @copydoc BlueprintNode::addToGraphviz - void addToGraphviz(std::ostream& os) const override; - /// Retrieve the binning configuration /// @return The binning configuration const std::optional& binning() const; @@ -83,6 +80,9 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { MaterialDesignatorBlueprintNode& setBinning(BinningConfig binning); private: + /// @copydoc BlueprintNode::addToGraphviz + void addToGraphviz(std::ostream& os) const override; + std::string m_name{}; std::optional m_binning{}; From 9d22b855f0e2322bbd0d0f972921c045f8eaa660 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 6 Dec 2024 09:56:58 +0100 Subject: [PATCH 081/100] spelling fixes --- Core/include/Acts/Geometry/Blueprint.hpp | 4 ++-- Core/include/Acts/Geometry/BlueprintNode.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/include/Acts/Geometry/Blueprint.hpp b/Core/include/Acts/Geometry/Blueprint.hpp index dc700a2488b..56d0a058177 100644 --- a/Core/include/Acts/Geometry/Blueprint.hpp +++ b/Core/include/Acts/Geometry/Blueprint.hpp @@ -47,7 +47,7 @@ class GeometryContext; /// The construction phases are documented in @c BlueprintNode, which is the /// base class for all nodes in the tree. /// @note This class inherits from @c BlueprintNode privately, because it is -/// only ever intented to be the top-level node, and not anywhere else in +/// only ever intended to be the top-level node, and not anywhere else in /// the tree. class Blueprint : private BlueprintNode { public: @@ -66,7 +66,7 @@ class Blueprint : private BlueprintNode { ExtentEnvelope envelope = ExtentEnvelope::Zero(); /// The geometry identifier hook, passed through the `TrackingGeometry` - /// constructor. This will be superceded by a more integrated approach to + /// constructor. This will be superseded by a more integrated approach to /// the identification scheme GeometryIdentifierHook geometryIdentifierHook = {}; }; diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index 74dcec91b92..62f164f0551 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -114,7 +114,7 @@ class BlueprintNode { /// - Creating navigation policies /// - (In future) Handle geometry identification assignment /// - /// At the end of this phase, each node will have transfered any temporary + /// At the end of this phase, each node will have transferred any temporary /// resources created during the build, that need to be retained, into the /// final @ref Acts::TrackingGeometry, and can be safely destroyed. /// @@ -138,7 +138,7 @@ class BlueprintNode { /// @name Convenience methods /// These methods are meant to make the construction of a blueprint tree in /// code more ergonomic. - /// They usually take an optional `callback` paramater. The primary use for + /// They usually take an optional `callback` parameter. The primary use for /// this parameter is structural, as it facilitates introducing scopes to /// indicate in code that objects are nested. /// From f641f0a031570ad2549a462874be2c75fb78b073 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 6 Dec 2024 10:06:30 +0100 Subject: [PATCH 082/100] fix doxygen errors --- .../include/Acts/Geometry/CylinderContainerBlueprintNode.hpp | 5 +++-- .../Acts/Geometry/MaterialDesignatorBlueprintNode.hpp | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index e218d3c207b..28bd6ab4e2d 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -48,7 +48,8 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { /// This participates in the construction of the geometry via the blueprint /// tree. The steps are approximately as follows: /// -# Collect all child volumes - /// -# Package them into a @ref Acts::CylinderVolumeStack, which performs sizing and/or gap cration + /// -# Package them into a @ref Acts::CylinderVolumeStack, which performs + /// sizing and/or gap creation /// -# Return the @ref Acts::CylinderVolumeStack as a volume up the tree /// /// @param options The global blueprint options @@ -81,7 +82,7 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { /// -# Register portals created for gap volumes, as they're not handled by /// dedicated nodes /// -# Register gap volumes in the @p parent volume - /// -# Create a configured @ref Acts::NavigationPolicy for the gap + /// -# Create a configured @ref Acts::INavigationPolicy for the gap /// -# Call `finalize` on all children while passing through @p parent. /// /// @param options The global blueprint options diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index dfb6ac77b00..88c080c585b 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -54,11 +54,12 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { /// It receives the populated portal shell from its only child and attaches /// material proxies by consulting the configuration stored in the node. /// @note Currently, this node will unconditionally attach - /// @ref Acrs::ProtoGridSurfaceMaterial + /// @ref Acts::ProtoGridSurfaceMaterial /// /// @param options The global blueprint options /// @param gctx The geometry context (nominal usually) /// @param logger The logger to use + /// @return The portal shell with material proxies attached PortalShellBase& connect( const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger = Acts::getDummyLogger()) override; @@ -68,6 +69,7 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { /// @param options The global blueprint options /// @param gctx The geometry context (nominal usually) /// @param parent The parent volume + /// @param logger The logger to use during construction void finalize(const BlueprintOptions& options, const GeometryContext& gctx, TrackingVolume& parent, const Logger& logger) override; From e70f022420c528531220d30ac940d074ad7df368 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 6 Dec 2024 10:07:06 +0100 Subject: [PATCH 083/100] move BlueprintOptions destructor to allow forward declaration --- Core/include/Acts/Geometry/BlueprintOptions.hpp | 2 ++ Core/src/Geometry/BlueprintOptions.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/Core/include/Acts/Geometry/BlueprintOptions.hpp b/Core/include/Acts/Geometry/BlueprintOptions.hpp index ca276289d51..90cba6cfa05 100644 --- a/Core/include/Acts/Geometry/BlueprintOptions.hpp +++ b/Core/include/Acts/Geometry/BlueprintOptions.hpp @@ -20,6 +20,8 @@ struct BlueprintOptions { void validate() const; + ~BlueprintOptions(); + private: static std::unique_ptr makeDefaultNavigationPolicyFactory(); diff --git a/Core/src/Geometry/BlueprintOptions.cpp b/Core/src/Geometry/BlueprintOptions.cpp index b1b46173116..4280fb24872 100644 --- a/Core/src/Geometry/BlueprintOptions.cpp +++ b/Core/src/Geometry/BlueprintOptions.cpp @@ -25,4 +25,7 @@ BlueprintOptions::makeDefaultNavigationPolicyFactory() { .add() .asUniquePtr(); } + +BlueprintOptions::~BlueprintOptions() = default; + } // namespace Acts From 925ff08dde9e66760571a8b3802d5126647e459c Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Fri, 6 Dec 2024 10:22:12 +0100 Subject: [PATCH 084/100] fix python bindigs and API --- .../Acts/Geometry/BlueprintOptions.hpp | 2 +- Core/src/Geometry/Blueprint.cpp | 2 - Examples/Python/src/Blueprint.cpp | 66 ++++++++++--------- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/Core/include/Acts/Geometry/BlueprintOptions.hpp b/Core/include/Acts/Geometry/BlueprintOptions.hpp index 90cba6cfa05..a2a698490c2 100644 --- a/Core/include/Acts/Geometry/BlueprintOptions.hpp +++ b/Core/include/Acts/Geometry/BlueprintOptions.hpp @@ -15,7 +15,7 @@ namespace Acts { class NavigationPolicyFactory; struct BlueprintOptions { - std::unique_ptr defaultNavigationPolicyFactory{ + std::shared_ptr defaultNavigationPolicyFactory{ makeDefaultNavigationPolicyFactory()}; void validate() const; diff --git a/Core/src/Geometry/Blueprint.cpp b/Core/src/Geometry/Blueprint.cpp index 33daee6734b..6c084f4647f 100644 --- a/Core/src/Geometry/Blueprint.cpp +++ b/Core/src/Geometry/Blueprint.cpp @@ -137,8 +137,6 @@ std::unique_ptr Blueprint::construct( child.finalize(options, gctx, *world, logger); - // @TODO: Maybe add a name uniqueness check - std::set names; world->visitVolumes([&](const auto *volume) { diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 4f2a865bdbe..41fde9ddaa9 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -225,18 +225,47 @@ void addBlueprint(Context& ctx) { py::class_>( m, "BlueprintNode"); + auto rootNode = + py::class_>(m, "Blueprint"); + + rootNode + .def(py::init()) + // Return value needs to be shared pointer because python otherwise + // can't manage the lifetime + .def( + "construct", + [](Blueprint& self, const BlueprintOptions& options, + const GeometryContext& gctx, + Logging::Level level) -> std::shared_ptr { + return self.construct(options, gctx, + *getDefaultLogger("Blueprint", level)); + }, + py::arg("options"), py::arg("gctx"), + py::arg("level") = Logging::INFO); + + { + auto c = py::class_(rootNode, "Config").def(py::init()); + ACTS_PYTHON_STRUCT_BEGIN(c, Blueprint::Config); + ACTS_PYTHON_MEMBER(envelope); + ACTS_PYTHON_MEMBER(geometryIdentifierHook); + ACTS_PYTHON_STRUCT_END(); + } + auto addContextManagerProtocol = [](class_& cls) { - using type = class_::type; + using type = typename class_::type; cls.def("__enter__", [](type& self) -> type& { return self; }) .def("__exit__", [](type& /*self*/, const py::object& /*exc_type*/, const py::object& /*exc_value*/, const py::object& /*traceback*/) {}); }; - auto addNodeMethods = [&blueprintNode](const std::string& name, - auto&& callable, auto&&... args) { + auto addNodeMethods = [&blueprintNode, &rootNode](const std::string& name, + auto&& callable, + auto&&... args) { blueprintNode.def(name.c_str(), callable, args...) .def(("add" + name).c_str(), callable, args...); + rootNode.def(name.c_str(), callable, args...) + .def(("add" + name).c_str(), callable, args...); }; blueprintNode @@ -257,9 +286,10 @@ void addBlueprint(Context& ctx) { fh.attr("write")(ss.str()); }); - // @TODO: Add ability to provide policy factories - // This needs a way to produce them in python! - py::class_(m, "BlueprintOptions").def(py::init<>()); + py::class_(m, "BlueprintOptions") + .def(py::init<>()) + .def_readwrite("defaultNavigationPolicyFactory", + &BlueprintOptions::defaultNavigationPolicyFactory); py::class_(blueprintNode, "MutableChildRange") @@ -283,30 +313,6 @@ void addBlueprint(Context& ctx) { return self.size(); }); - { - auto n = py::class_>(m, "Blueprint"); - - n.def(py::init()) - // Return value needs to be shared pointer because python otherwise - // can't manage the lifetime - .def( - "construct", - [](Blueprint& self, const BlueprintOptions& options, - const GeometryContext& gctx, - Logging::Level level) -> std::shared_ptr { - return self.construct(options, gctx, - *getDefaultLogger("Blueprint", level)); - }, - py::arg("options"), py::arg("gctx"), - py::arg("level") = Logging::INFO); - - auto c = py::class_(n, "Config").def(py::init()); - ACTS_PYTHON_STRUCT_BEGIN(c, Blueprint::Config); - ACTS_PYTHON_MEMBER(envelope); - ACTS_PYTHON_MEMBER(geometryIdentifierHook); - ACTS_PYTHON_STRUCT_END(); - } - auto staticNode = py::class_>( From 9ee0627db8796763b8e78b463b2da7d683e2aef7 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 9 Dec 2024 13:29:28 +0100 Subject: [PATCH 085/100] drop private inheritance (likely not worth the hassle) --- Core/include/Acts/Geometry/Blueprint.hpp | 11 +---------- Examples/Python/src/Blueprint.cpp | 10 ++++------ 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/Core/include/Acts/Geometry/Blueprint.hpp b/Core/include/Acts/Geometry/Blueprint.hpp index 56d0a058177..cdc8af57a42 100644 --- a/Core/include/Acts/Geometry/Blueprint.hpp +++ b/Core/include/Acts/Geometry/Blueprint.hpp @@ -49,17 +49,8 @@ class GeometryContext; /// @note This class inherits from @c BlueprintNode privately, because it is /// only ever intended to be the top-level node, and not anywhere else in /// the tree. -class Blueprint : private BlueprintNode { +class Blueprint : public BlueprintNode { public: - // Pull in convenience methods, despite privately inheriting - using BlueprintNode::addChild; - using BlueprintNode::addCylinderContainer; - using BlueprintNode::addLayer; - using BlueprintNode::addMaterial; - using BlueprintNode::addStaticVolume; - using BlueprintNode::children; - using BlueprintNode::graphViz; - struct Config { /// Determine how much envelope space to produce from the highest volume /// in the geometry hierarchy and the world volume. diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 41fde9ddaa9..1d53ae8d6fc 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -226,7 +226,8 @@ void addBlueprint(Context& ctx) { m, "BlueprintNode"); auto rootNode = - py::class_>(m, "Blueprint"); + py::class_>( + m, "Blueprint"); rootNode .def(py::init()) @@ -259,13 +260,10 @@ void addBlueprint(Context& ctx) { const py::object& /*traceback*/) {}); }; - auto addNodeMethods = [&blueprintNode, &rootNode](const std::string& name, - auto&& callable, - auto&&... args) { + auto addNodeMethods = [&blueprintNode](const std::string& name, + auto&& callable, auto&&... args) { blueprintNode.def(name.c_str(), callable, args...) .def(("add" + name).c_str(), callable, args...); - rootNode.def(name.c_str(), callable, args...) - .def(("add" + name).c_str(), callable, args...); }; blueprintNode From 28f9a81d5e53fe26890a416b592892746f56a021 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 9 Dec 2024 13:29:50 +0100 Subject: [PATCH 086/100] add decrement depth protected method and call when clearing children --- Core/include/Acts/Geometry/BlueprintNode.hpp | 3 +++ Core/src/Geometry/BlueprintNode.cpp | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index 62f164f0551..29cc390cc8f 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -281,6 +281,9 @@ class BlueprintNode { /// Increase the depth of this node and all descendents by one. void incrementDepth(); + /// Decrease the depth of this node and all descendents by one. + void decrementDepth(); + /// Printing helper returning a prefix including an indent depending on the /// depth. /// @return The prefix string diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index 94a7a330552..6d5d9434795 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -77,6 +77,13 @@ void BlueprintNode::incrementDepth() { } } +void BlueprintNode::decrementDepth() { + m_depth--; + for (auto& child : m_children) { + child->decrementDepth(); + } +} + std::string BlueprintNode::indent() const { return std::string(m_depth * 2, ' '); } @@ -147,6 +154,9 @@ LayerBlueprintNode& BlueprintNode::addLayer( } void BlueprintNode::clearChildren() { + for (auto& child : m_children) { + child->decrementDepth(); + } m_children.clear(); } From bc93d985a68a78c155162810be7df5e5bffd0204 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 9 Dec 2024 13:33:26 +0100 Subject: [PATCH 087/100] fix redundant policy construction --- Core/src/Geometry/CylinderContainerBlueprintNode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index aa5c706ee44..9264c38eec0 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -171,7 +171,7 @@ void CylinderContainerBlueprintNode::finalize(const BlueprintOptions& options, parent.addVolume(std::move(gap)); shell->applyToVolume(); auto policy = policyFactory->build(gctx, *gapPtr, logger); - gapPtr->setNavigationPolicy(policyFactory->build(gctx, *gapPtr, logger)); + gapPtr->setNavigationPolicy(std::move(policy)); } ACTS_DEBUG(prefix() << "Finalizing " << children().size() << " children"); From c94102c11574b86142cc3e3171c5cfb97dd39eb4 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 9 Dec 2024 13:39:44 +0100 Subject: [PATCH 088/100] add missing docs listings --- docs/core/geometry/concepts.md | 12 ++++++++++++ docs/core/geometry/construction.md | 17 ++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/core/geometry/concepts.md b/docs/core/geometry/concepts.md index 7575a5cb610..58e0b07ff36 100644 --- a/docs/core/geometry/concepts.md +++ b/docs/core/geometry/concepts.md @@ -32,6 +32,9 @@ Not complete yet :::{doxygenclass} Acts::GridPortalLink ::: +:::{doxygenclass} Acts::GridPortalLinkT +::: + #### Composite portal link :::{doxygenclass} Acts::CompositePortalLink @@ -39,4 +42,13 @@ Not complete yet ### Portal shells +:::{doxygenclass} Acts::PortalShellBase +::: + +:::{doxygenclass} Acts::SingleCylinderPortalShell +::: + +:::{doxygenclass} Acts::CylinderStackPortalShell +::: + ### Navigation policy diff --git a/docs/core/geometry/construction.md b/docs/core/geometry/construction.md index 44c38ed3022..5bcebdb24be 100644 --- a/docs/core/geometry/construction.md +++ b/docs/core/geometry/construction.md @@ -9,13 +9,28 @@ Not complete yet :::{doxygenclass} Acts::BlueprintNode ::: +:::{doxygenclass} Acts::Blueprint +::: + ### Container nodes +:::{doxygenclass} Acts::CylinderContainerBlueprintNode +::: + ### Material nodes +:::{doxygenclass} Acts::MaterialDesignatorBlueprintNode +::: + ### Geometry identification specification -### *Layers* +### *Layers* and other nodes + +:::{doxygenclass} Acts::StaticBlueprintNode +::: + +:::{doxygenclass} Acts::LayerBlueprintNode +::: ## API From 2c0f4304bbc5a0bde807dfabeae511507a4fc882 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 9 Dec 2024 13:41:07 +0100 Subject: [PATCH 089/100] don't decrement depth when it's already zero --- Core/src/Geometry/BlueprintNode.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index 6d5d9434795..92252df4856 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -78,7 +78,10 @@ void BlueprintNode::incrementDepth() { } void BlueprintNode::decrementDepth() { - m_depth--; + if (m_depth == 0) { + return; + } + for (auto& child : m_children) { child->decrementDepth(); } From d528dfbff5f3db7f3fc0da17b6c51ee44ba94209 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 9 Dec 2024 13:44:03 +0100 Subject: [PATCH 090/100] more classes --- docs/core/geometry/concepts.md | 6 ++++++ docs/core/geometry/layerless/layerless.md | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/core/geometry/concepts.md b/docs/core/geometry/concepts.md index 58e0b07ff36..8fa995534e4 100644 --- a/docs/core/geometry/concepts.md +++ b/docs/core/geometry/concepts.md @@ -45,6 +45,9 @@ Not complete yet :::{doxygenclass} Acts::PortalShellBase ::: +:::{doxygenclass} Acts::CylinderPortalShell +::: + :::{doxygenclass} Acts::SingleCylinderPortalShell ::: @@ -52,3 +55,6 @@ Not complete yet ::: ### Navigation policy + +:::{doxygenclass} Acts::INavigationPolicy +::: diff --git a/docs/core/geometry/layerless/layerless.md b/docs/core/geometry/layerless/layerless.md index 7fdc0d83516..300b44f7eb4 100644 --- a/docs/core/geometry/layerless/layerless.md +++ b/docs/core/geometry/layerless/layerless.md @@ -5,7 +5,7 @@ ## Geometry module rosetta stone :::{note} -The combination of the original (Gen 1) geometry classes and the new *layerless* modelling (Gen 2, this page) will result in a combined Gen 3 geometry model. It will be documented [here](core/geometry/index.md) when completed. +The combination of the original (Gen 1) geometry classes and the new *layerless* modelling (Gen 2, this page) will result in a combined Gen 3 geometry model. It will be documented [here](core/geometry/index) when completed. ::: :::{toctree} From 6774c7ba8bcfa47975c9e1c7727afcddd14e17b7 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 9 Dec 2024 18:47:54 +0100 Subject: [PATCH 091/100] (hopefully) fix depth issues --- Core/include/Acts/Geometry/BlueprintNode.hpp | 7 ++----- Core/src/Geometry/BlueprintNode.cpp | 20 +++++--------------- Examples/Python/src/Blueprint.cpp | 1 + Examples/Python/tests/test_blueprint.py | 19 ++++++++++++++++--- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index 29cc390cc8f..62014188baa 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -278,11 +278,8 @@ class BlueprintNode { /// @note This method is called by the stream operator. virtual void toStream(std::ostream& os) const; - /// Increase the depth of this node and all descendents by one. - void incrementDepth(); - - /// Decrease the depth of this node and all descendents by one. - void decrementDepth(); + /// Set the depth to @p depth and update children recursively + void setDepth(std::size_t depth); /// Printing helper returning a prefix including an indent depending on the /// depth. diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index 92252df4856..a45c589d22e 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -53,7 +53,7 @@ BlueprintNode& BlueprintNode::addChild(std::shared_ptr child) { throw std::invalid_argument("Adding child would create a cycle"); } - child->incrementDepth(); + child->setDepth(m_depth + 1); m_children.push_back(std::move(child)); return *this; } @@ -70,20 +70,10 @@ std::size_t BlueprintNode::depth() const { return m_depth; } -void BlueprintNode::incrementDepth() { - m_depth++; +void BlueprintNode::setDepth(std::size_t depth) { + m_depth = depth; for (auto& child : m_children) { - child->incrementDepth(); - } -} - -void BlueprintNode::decrementDepth() { - if (m_depth == 0) { - return; - } - - for (auto& child : m_children) { - child->decrementDepth(); + child->setDepth(depth + 1); } } @@ -158,7 +148,7 @@ LayerBlueprintNode& BlueprintNode::addLayer( void BlueprintNode::clearChildren() { for (auto& child : m_children) { - child->decrementDepth(); + child->setDepth(0); } m_children.clear(); } diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 1d53ae8d6fc..510974666e1 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -278,6 +278,7 @@ void addBlueprint(Context& ctx) { py::overload_cast<>(&BlueprintNode::children)) .def("clearChildren", &BlueprintNode::clearChildren) .def_property_readonly("name", &BlueprintNode::name) + .def_property_readonly("depth", &BlueprintNode::depth) .def("graphViz", [](BlueprintNode& self, const py::object& fh) { std::stringstream ss; self.graphViz(ss); diff --git a/Examples/Python/tests/test_blueprint.py b/Examples/Python/tests/test_blueprint.py index 6964be2abff..dbaca790cb4 100644 --- a/Examples/Python/tests/test_blueprint.py +++ b/Examples/Python/tests/test_blueprint.py @@ -23,22 +23,31 @@ def write(root: acts.BlueprintNode, stage: int): base = acts.Transform3.Identity() root = acts.Blueprint(envelope=acts.ExtentEnvelope(r=[10 * mm, 10 * mm])) + assert root.depth == 0 barrel = root.addCylinderContainer("Barrel", direction=bv.binR) + assert barrel.depth == 1 + r = 25 * mm for i in range(1, 3): r += 50 * mm bounds = acts.CylinderVolumeBounds(r, r + 20 * mm, 200 * mm) - barrel.addStaticVolume(base, bounds, name=f"Barrel_{i}") + vol = barrel.addStaticVolume(base, bounds, name=f"Barrel_{i}") + assert vol.depth == 2 write(barrel, 1) root.clearChildren() + assert barrel.depth == 0 + det = root.addCylinderContainer("Detector", direction=bv.binZ) + assert det.depth == 1 + with det.CylinderContainer("nEC", direction=bv.binZ) as ec: + assert ec.depth == 2 z = -200 for i in range(1, 3): z -= 200 * mm @@ -46,15 +55,18 @@ def write(root: acts.BlueprintNode, stage: int): trf = base * acts.Translation3(acts.Vector3(0, 0, z)) - ec.addStaticVolume(trf, bounds, name=f"nEC_{i}") + vol = ec.addStaticVolume(trf, bounds, name=f"nEC_{i}") + assert vol.depth == 3 write(ec, 2) det.addChild(barrel) + assert barrel.depth == 2 write(det, 3) with det.CylinderContainer("pEC", direction=bv.binZ) as ec: + assert ec.depth == 2 z = 200 for i in range(1, 3): z += 200 * mm @@ -62,6 +74,7 @@ def write(root: acts.BlueprintNode, stage: int): trf = base * acts.Translation3(acts.Vector3(0, 0, z)) - ec.addStaticVolume(trf, bounds, name=f"pEC_{i}") + vol = ec.addStaticVolume(trf, bounds, name=f"pEC_{i}") + assert vol.depth == 3 write(root, 4) From 1e0fe9406f09c3c47c0bf634312b3905e076a96f Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 9 Dec 2024 18:50:25 +0100 Subject: [PATCH 092/100] more docs refs --- docs/core/geometry/concepts.md | 12 ++++++++++++ docs/core/geometry/layerless/layerless.md | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/core/geometry/concepts.md b/docs/core/geometry/concepts.md index 8fa995534e4..86cde2efd6f 100644 --- a/docs/core/geometry/concepts.md +++ b/docs/core/geometry/concepts.md @@ -58,3 +58,15 @@ Not complete yet :::{doxygenclass} Acts::INavigationPolicy ::: + +:::{doxygenclass} Acts::MultiNavigationPolicyBase +::: + +:::{doxygenclass} Acts::SurfaceArrayNavigationPolicy +::: + +:::{doxygenclass} Acts::TryAllNavigationPolicy +::: + +:::{doxygenclass} Acts::ProtoLayer +::: diff --git a/docs/core/geometry/layerless/layerless.md b/docs/core/geometry/layerless/layerless.md index 300b44f7eb4..2142f5b357b 100644 --- a/docs/core/geometry/layerless/layerless.md +++ b/docs/core/geometry/layerless/layerless.md @@ -5,7 +5,7 @@ ## Geometry module rosetta stone :::{note} -The combination of the original (Gen 1) geometry classes and the new *layerless* modelling (Gen 2, this page) will result in a combined Gen 3 geometry model. It will be documented [here](core/geometry/index) when completed. +The combination of the original (Gen 1) geometry classes and the new *layerless* modelling (Gen 2, this page) will result in a combined Gen 3 geometry model. It will be documented [here](core/geometry) when completed. ::: :::{toctree} From 80324ef26421f4622704bb071655b00d7c92bd05 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Mon, 9 Dec 2024 18:50:39 +0100 Subject: [PATCH 093/100] drop forward decl, missing includes doesn't like it --- Core/include/Acts/Geometry/BlueprintOptions.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/include/Acts/Geometry/BlueprintOptions.hpp b/Core/include/Acts/Geometry/BlueprintOptions.hpp index a2a698490c2..6e3447d9219 100644 --- a/Core/include/Acts/Geometry/BlueprintOptions.hpp +++ b/Core/include/Acts/Geometry/BlueprintOptions.hpp @@ -8,12 +8,12 @@ #pragma once +#include "Acts/Geometry/NavigationPolicyFactory.hpp" + #include namespace Acts { -class NavigationPolicyFactory; - struct BlueprintOptions { std::shared_ptr defaultNavigationPolicyFactory{ makeDefaultNavigationPolicyFactory()}; From 390c8d9fc73f22f833188b04a579c94d652fdb8f Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 10 Dec 2024 10:25:19 +0100 Subject: [PATCH 094/100] try to fix docs issues --- docs/core/geometry/concepts.md | 5 ++++- docs/core/geometry/layerless/layerless.md | 2 +- docs/known-warnings.txt | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/core/geometry/concepts.md b/docs/core/geometry/concepts.md index 86cde2efd6f..abd2d31951a 100644 --- a/docs/core/geometry/concepts.md +++ b/docs/core/geometry/concepts.md @@ -62,11 +62,14 @@ Not complete yet :::{doxygenclass} Acts::MultiNavigationPolicyBase ::: +:::{doxygenclass} Acts::MultiNavigationPolicy +::: + :::{doxygenclass} Acts::SurfaceArrayNavigationPolicy ::: :::{doxygenclass} Acts::TryAllNavigationPolicy ::: -:::{doxygenclass} Acts::ProtoLayer +:::{doxygenstruct} Acts::ProtoLayer ::: diff --git a/docs/core/geometry/layerless/layerless.md b/docs/core/geometry/layerless/layerless.md index 2142f5b357b..98e1624592a 100644 --- a/docs/core/geometry/layerless/layerless.md +++ b/docs/core/geometry/layerless/layerless.md @@ -5,7 +5,7 @@ ## Geometry module rosetta stone :::{note} -The combination of the original (Gen 1) geometry classes and the new *layerless* modelling (Gen 2, this page) will result in a combined Gen 3 geometry model. It will be documented [here](core/geometry) when completed. +The combination of the original (Gen 1) geometry classes and the new *layerless* modelling (Gen 2, this page) will result in a combined Gen 3 geometry model. ::: :::{toctree} diff --git a/docs/known-warnings.txt b/docs/known-warnings.txt index 2138dc11bb9..2c23b8a9319 100644 --- a/docs/known-warnings.txt +++ b/docs/known-warnings.txt @@ -5,5 +5,6 @@ .*Duplicate explicit target name: .* .*undefined label: .*class_acts_1_1_convex_polygon_bounds_3_01_polygon_dynamic_01_4.* .*undefined label: .*class_acts_1_1_grid_surface_material_t.* +.*undefined label: .*namespace_acts_.* # I think these are because we use specialization .*undefined label: .*bdt.* From b6f3b8be19d185df8da191d5fa87718b27978c2f Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 10 Dec 2024 10:56:59 +0100 Subject: [PATCH 095/100] sonar fixes --- Core/include/Acts/Geometry/Blueprint.hpp | 2 +- .../CylinderContainerBlueprintNode.hpp | 4 + .../Acts/Geometry/LayerBlueprintNode.hpp | 2 +- .../MaterialDesignatorBlueprintNode.hpp | 10 +- .../Acts/Geometry/StaticBlueprintNode.hpp | 2 +- Core/src/Geometry/Blueprint.cpp | 11 +- Core/src/Geometry/BlueprintNode.cpp | 8 +- .../CylinderContainerBlueprintNode.cpp | 39 +++--- .../MaterialDesignatorBlueprintNode.cpp | 117 ++++++++++-------- Examples/Python/src/Blueprint.cpp | 14 +-- .../Core/Geometry/BlueprintTests.cpp | 2 +- 11 files changed, 117 insertions(+), 94 deletions(-) diff --git a/Core/include/Acts/Geometry/Blueprint.hpp b/Core/include/Acts/Geometry/Blueprint.hpp index cdc8af57a42..c957466601b 100644 --- a/Core/include/Acts/Geometry/Blueprint.hpp +++ b/Core/include/Acts/Geometry/Blueprint.hpp @@ -64,7 +64,7 @@ class Blueprint : public BlueprintNode { /// Constructor from a config object /// @param config The configuration object - Blueprint(const Config& config); + explicit Blueprint(const Config& config); /// Construct the tracking geometry from the blueprint tree /// @param options The construction options, see @c BlueprintOptions diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index 28bd6ab4e2d..5b2c54c57b5 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -130,6 +130,10 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { /// @return True if the volume is a gap volume, false otherwise bool isGapVolume(const Volume& volume) const; + std::vector collectChildShells( + const BlueprintOptions& options, const GeometryContext& gctx, + const Logger& logger); + std::string m_name; BinningValue m_direction; diff --git a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp index 8ca3f3ca40e..999a8272a8e 100644 --- a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp @@ -44,7 +44,7 @@ class LayerBlueprintNode : public StaticBlueprintNode { /// Constructor for a layer node. /// @param name The name of the layer - LayerBlueprintNode(const std::string& name) + explicit LayerBlueprintNode(const std::string& name) : StaticBlueprintNode{nullptr}, m_name(name) {} /// @copydoc BlueprintNode::name diff --git a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp index 88c080c585b..dbb4663fe71 100644 --- a/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/MaterialDesignatorBlueprintNode.hpp @@ -32,7 +32,8 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { /// Main constructor for the material designator node. /// @param name The name of the node (for debug only) - MaterialDesignatorBlueprintNode(const std::string& name) : m_name(name) {} + explicit MaterialDesignatorBlueprintNode(const std::string& name) + : m_name(name) {} /// @copydoc BlueprintNode::name const std::string& name() const override; @@ -85,6 +86,13 @@ class MaterialDesignatorBlueprintNode final : public BlueprintNode { /// @copydoc BlueprintNode::addToGraphviz void addToGraphviz(std::ostream& os) const override; + void handleCylinderBinning( + CylinderPortalShell& cylShell, + const std::vector< + std::tuple>& binning, + const Logger& logger); + std::string m_name{}; std::optional m_binning{}; diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index b6952b418d2..ca2843badc0 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -26,7 +26,7 @@ class StaticBlueprintNode : public BlueprintNode { public: /// Construct the static node from an existing volume /// @param volume The volume to wrap - StaticBlueprintNode(std::unique_ptr volume); + explicit StaticBlueprintNode(std::unique_ptr volume); /// Get the name of this node. It is automatically taken from the wrapped /// volume diff --git a/Core/src/Geometry/Blueprint.cpp b/Core/src/Geometry/Blueprint.cpp index 6c084f4647f..8d7cb56b567 100644 --- a/Core/src/Geometry/Blueprint.cpp +++ b/Core/src/Geometry/Blueprint.cpp @@ -16,13 +16,16 @@ #include "Acts/Navigation/INavigationPolicy.hpp" #include "Acts/Utilities/GraphViz.hpp" +namespace { +inline static const std::string s_rootName = "Root"; +} + namespace Acts { Blueprint::Blueprint(const Config &config) : m_cfg(config) {} const std::string &Blueprint::name() const { - static const std::string root = "Root"; - return root; + return s_rootName; } Volume &Blueprint::build(const BlueprintOptions & /*options*/, @@ -137,9 +140,9 @@ std::unique_ptr Blueprint::construct( child.finalize(options, gctx, *world, logger); - std::set names; + std::set> names; - world->visitVolumes([&](const auto *volume) { + world->visitVolumes([&names, &logger, this](const auto *volume) { if (names.contains(volume->volumeName())) { ACTS_ERROR(prefix() << "Duplicate volume name: " << volume->volumeName()); throw std::logic_error("Duplicate volume name"); diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index a45c589d22e..f45b9832765 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -72,8 +72,8 @@ std::size_t BlueprintNode::depth() const { void BlueprintNode::setDepth(std::size_t depth) { m_depth = depth; - for (auto& child : m_children) { - child->setDepth(depth + 1); + for (auto& child : children()) { + child.setDepth(depth + 1); } } @@ -147,8 +147,8 @@ LayerBlueprintNode& BlueprintNode::addLayer( } void BlueprintNode::clearChildren() { - for (auto& child : m_children) { - child->setDepth(0); + for (auto& child : children()) { + child.setDepth(0); } m_children.clear(); } diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 9264c38eec0..284b30949ac 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -67,23 +67,11 @@ Volume& CylinderContainerBlueprintNode::build(const BlueprintOptions& options, return *m_stack; } -CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( +std::vector +CylinderContainerBlueprintNode::collectChildShells( const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger) { - ACTS_DEBUG(prefix() << "Cylinder container connect"); - if (m_stack == nullptr) { - ACTS_ERROR(prefix() << "Volume is not built"); - throw std::runtime_error("Volume is not built"); - } - std::vector shells; - ACTS_DEBUG(prefix() << "Collecting child shells from " << children().size() - << " children"); - - // We have child volumes and gaps as bare Volumes in `m_childVolumes` after - // `build()` has completed. For the stack shell, we need TrackingVolumes in - // the right order. - ACTS_DEBUG(prefix() << "Have " << m_childVolumes.size() << " child volumes"); for (Volume* volume : m_childVolumes) { if (isGapVolume(*volume)) { @@ -109,7 +97,7 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( ACTS_DEBUG(prefix() << " ~> Child (" << child.name() << ") volume: " << volume->volumeBounds()); - CylinderPortalShell* shell = dynamic_cast( + auto* shell = dynamic_cast( &child.connect(options, gctx, logger)); if (shell == nullptr) { ACTS_ERROR(prefix() @@ -122,6 +110,27 @@ CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( shells.push_back(shell); } } + return shells; +} + +CylinderStackPortalShell& CylinderContainerBlueprintNode::connect( + const BlueprintOptions& options, const GeometryContext& gctx, + const Logger& logger) { + ACTS_DEBUG(prefix() << "Cylinder container connect"); + if (m_stack == nullptr) { + ACTS_ERROR(prefix() << "Volume is not built"); + throw std::runtime_error("Volume is not built"); + } + + ACTS_DEBUG(prefix() << "Collecting child shells from " << children().size() + << " children"); + + // We have child volumes and gaps as bare Volumes in `m_childVolumes` after + // `build()` has completed. For the stack shell, we need TrackingVolumes in + // the right order. + + std::vector shells = + collectChildShells(options, gctx, logger); // Sanity checks throw_assert(shells.size() == m_childVolumes.size(), diff --git a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp index 5c1f1218010..0e89b65d6e3 100644 --- a/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp +++ b/Core/src/Geometry/MaterialDesignatorBlueprintNode.cpp @@ -45,6 +45,54 @@ Volume& MaterialDesignatorBlueprintNode::build(const BlueprintOptions& options, return children().at(0).build(options, gctx, logger); } +void MaterialDesignatorBlueprintNode::handleCylinderBinning( + CylinderPortalShell& cylShell, + const std::vector< + std::tuple>& binning, + const Logger& logger) { + ACTS_DEBUG(prefix() << "Binning is set to compatible type"); + using enum CylinderVolumeBounds::Face; + + for (auto& [face, loc0, loc1] : binning) { + if (face == OuterCylinder || face == InnerCylinder) { + if (loc0.binValue != BinningValue::binRPhi) { + ACTS_ERROR(prefix() << "Binning is not in RPhi"); + throw std::runtime_error("Binning is not in RPhi"); + } + + if (loc1.binValue != BinningValue::binZ) { + ACTS_ERROR(prefix() << "Binning is not in Z"); + throw std::runtime_error("Binning is not in Z"); + } + } + + if (face == PositiveDisc || face == NegativeDisc) { + if (loc0.binValue != BinningValue::binR) { + ACTS_ERROR(prefix() << "Binning is not in R"); + throw std::runtime_error("Binning is not in R"); + } + if (loc1.binValue != BinningValue::binPhi) { + ACTS_ERROR(prefix() << "Binning is not in Phi"); + throw std::runtime_error("Binning is not in Phi"); + } + } + + Experimental::BinningDescription desc{.binning = {loc0, loc1}}; + ACTS_DEBUG(prefix() << "~> Assigning proto binning " << desc.toString() + << " to face " << face); + + auto material = std::make_shared(std::move(desc)); + + auto portal = cylShell.portal(face); + if (portal == nullptr) { + ACTS_ERROR(prefix() << "Portal is nullptr"); + throw std::runtime_error("Portal is nullptr"); + } + portal->surface().assignSurfaceMaterial(std::move(material)); + } +} + PortalShellBase& MaterialDesignatorBlueprintNode::connect( const BlueprintOptions& options, const GeometryContext& gctx, const Logger& logger) { @@ -69,61 +117,18 @@ PortalShellBase& MaterialDesignatorBlueprintNode::connect( if (auto* cylShell = dynamic_cast(&shell)) { ACTS_DEBUG(prefix() << "Connecting cylinder shell"); - std::visit( - overloaded{ - [&](const std::vector>& binning) { - ACTS_DEBUG(prefix() << "Binning is set to compatible type"); - using enum CylinderVolumeBounds::Face; - - for (auto& [face, loc0, loc1] : binning) { - if (face == OuterCylinder || face == InnerCylinder) { - if (loc0.binValue != BinningValue::binRPhi) { - ACTS_ERROR(prefix() << "Binning is not in RPhi"); - throw std::runtime_error("Binning is not in RPhi"); - } - - if (loc1.binValue != BinningValue::binZ) { - ACTS_ERROR(prefix() << "Binning is not in Z"); - throw std::runtime_error("Binning is not in Z"); - } - } - - if (face == PositiveDisc || face == NegativeDisc) { - if (loc0.binValue != BinningValue::binR) { - ACTS_ERROR(prefix() << "Binning is not in R"); - throw std::runtime_error("Binning is not in R"); - } - if (loc1.binValue != BinningValue::binPhi) { - ACTS_ERROR(prefix() << "Binning is not in Phi"); - throw std::runtime_error("Binning is not in Phi"); - } - } - - Experimental::BinningDescription desc{.binning = {loc0, loc1}}; - ACTS_DEBUG(prefix() << "~> Assigning proto binning " - << desc.toString() << " to face " << face); - - auto material = - std::make_shared(std::move(desc)); - - auto portal = cylShell->portal(face); - if (portal == nullptr) { - ACTS_ERROR(prefix() << "Portal is nullptr"); - throw std::runtime_error("Portal is nullptr"); - } - portal->surface().assignSurfaceMaterial(std::move(material)); - } - }, - [&](const auto& /*binning*/) { - ACTS_ERROR(prefix() << "Binning is set to unknown type"); - throw std::runtime_error("Unknown binning type"); - }, - }, - m_binning.value()); + if (const auto* binning = std::get_if>>(&m_binning.value()); + binning != nullptr) { + handleCylinderBinning(*cylShell, *binning, logger); + } else { + ACTS_ERROR(prefix() << "Binning is set to unknown type"); + throw std::runtime_error("Unknown binning type"); + } + } - // @TODO: Handle cuboid volume shell + // @TODO: Handle cuboid volume shell here else { ACTS_ERROR(prefix() << "Shell is not supported"); throw std::runtime_error("Shell is not supported"); @@ -163,7 +168,9 @@ void MaterialDesignatorBlueprintNode::addToGraphviz(std::ostream& os) const { ss << ", " << loc1.binValue << "=" << loc1.bins(); } }, - [&](const auto& /*binning*/) {}}, + [](const auto& /*binning*/) { + // No output in all other cases + }}, m_binning.value()); os << GraphViz::Node{ .id = name(), .label = ss.str(), .shape = GraphViz::Shape::Hexagon}; diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 510974666e1..3d3088fd4b7 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -134,15 +134,6 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, ACTS_VERBOSE( "Already on surface at initialization, skipping candidate"); - // auto id = main.currentCandidate().surface().geometryId(); - // csv << run << "," << position[0] << "," << position[1] << "," - // << position[2]; - // csv << "," << id.volume(); - // csv << "," << id.boundary(); - // csv << "," << id.sensitive(); - - // csv << std::endl; - writeIntersection(position, main.currentCandidate().surface()); if (!main.switchToNextCandidate()) { @@ -168,7 +159,6 @@ void pseudoNavigation(const TrackingGeometry& trackingGeometry, std::max(1l, std::lround(delta.norm() / 10_cm * substepsPerCm)); for (std::size_t j = 0; j < substeps; j++) { - // position += delta / (substeps + 1); Vector3 subpos = position + subStepDist(rng) * delta; csv << run << "," << subpos[0] << "," << subpos[1] << "," << subpos[2]; @@ -257,7 +247,9 @@ void addBlueprint(Context& ctx) { cls.def("__enter__", [](type& self) -> type& { return self; }) .def("__exit__", [](type& /*self*/, const py::object& /*exc_type*/, const py::object& /*exc_value*/, - const py::object& /*traceback*/) {}); + const py::object& /*traceback*/) { + // No action needed on exit + }); }; auto addNodeMethods = [&blueprintNode](const std::string& name, diff --git a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp index 394ac3f05fe..743fedb4f50 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp @@ -93,7 +93,7 @@ BOOST_AUTO_TEST_CASE(InvalidRoot) { class DummyNode : public BlueprintNode { public: - DummyNode(const std::string& name) : m_name(name) {} + explicit DummyNode(const std::string& name) : m_name(name) {} const std::string& name() const override { return m_name; } From 405dbe3c22297360a22265f5cc19e6e0d50b4a4b Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 10 Dec 2024 11:13:00 +0100 Subject: [PATCH 096/100] add test that root node is not added as a child --- Core/src/Geometry/BlueprintNode.cpp | 5 +++++ Tests/UnitTests/Core/Geometry/BlueprintTests.cpp | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index f45b9832765..f0d41f6b568 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -8,6 +8,7 @@ #include "Acts/Geometry/BlueprintNode.hpp" +#include "Acts/Geometry/Blueprint.hpp" #include "Acts/Geometry/CylinderContainerBlueprintNode.hpp" #include "Acts/Geometry/LayerBlueprintNode.hpp" #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" @@ -45,6 +46,10 @@ BlueprintNode& BlueprintNode::addChild(std::shared_ptr child) { throw std::invalid_argument("Child is nullptr"); } + if (dynamic_cast(child.get()) != nullptr) { + throw std::invalid_argument("Cannot add a Blueprint as a child"); + } + if (child->depth() != 0) { throw std::invalid_argument("Child has already been added to another node"); } diff --git a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp index 743fedb4f50..c3a0ecc028f 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp @@ -119,6 +119,14 @@ class DummyNode : public BlueprintNode { std::string m_name; }; +BOOST_AUTO_TEST_CASE(RootCannotBeChild) { + auto node = std::make_shared("node"); + Blueprint::Config cfg; + auto root = std::make_shared(cfg); + + BOOST_CHECK_THROW(node->addChild(root), std::invalid_argument); +} + BOOST_AUTO_TEST_CASE(AddChildInvalid) { auto node = std::make_shared("node"); From 364ba599a0718e88421c7205787c3e048c0a8853 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 10 Dec 2024 13:54:32 +0100 Subject: [PATCH 097/100] feat: Make TransformRange fulfill range concept This allows using it with range algorithms --- .../include/Acts/Utilities/TransformRange.hpp | 14 +++++++++++ .../Core/Utilities/TransformRangeTests.cpp | 24 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/Core/include/Acts/Utilities/TransformRange.hpp b/Core/include/Acts/Utilities/TransformRange.hpp index 4c7653c49e2..b3df0447590 100644 --- a/Core/include/Acts/Utilities/TransformRange.hpp +++ b/Core/include/Acts/Utilities/TransformRange.hpp @@ -169,6 +169,8 @@ struct TransformRangeIterator { /// Construct an iterator from an underlying iterator explicit TransformRangeIterator(iterator_t iterator) : m_iterator(iterator) {} + TransformRangeIterator() = default; + /// Return a reference to the value that is transformed by the callable /// @return Reference to the transformed value reference operator*() { return Callable::apply(*m_iterator); } @@ -184,6 +186,14 @@ struct TransformRangeIterator { return *this; } + /// Advance the iterator + /// @return Reference to the iterator + TransformRangeIterator operator++(int) { + auto tmp = *this; + ++m_iterator; + return tmp; + } + /// Compare two iterators for equality /// @param other The other iterator to compare to bool operator==(const TransformRangeIterator& other) const { @@ -219,3 +229,7 @@ struct DotGet { }; } // namespace Acts::detail + +template +constexpr bool std::ranges::enable_borrowed_range< + Acts::detail::TransformRange> = true; diff --git a/Tests/UnitTests/Core/Utilities/TransformRangeTests.cpp b/Tests/UnitTests/Core/Utilities/TransformRangeTests.cpp index d7ce6b56877..3b369d56307 100644 --- a/Tests/UnitTests/Core/Utilities/TransformRangeTests.cpp +++ b/Tests/UnitTests/Core/Utilities/TransformRangeTests.cpp @@ -6,10 +6,13 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. +#include #include #include "Acts/Utilities/TransformRange.hpp" +#include + using namespace Acts; BOOST_AUTO_TEST_SUITE(TransformRangeTests) @@ -99,6 +102,14 @@ BOOST_AUTO_TEST_CASE(TransformRangeDeref) { static_assert(std::is_same_v); checkSameAddresses(v, r); + std::vector unpacked; + std::ranges::transform(r, std::back_inserter(unpacked), + [](auto val) { return val; }); + std::vector exp = {1, 2, 4}; + + BOOST_CHECK_EQUAL_COLLECTIONS(exp.begin(), exp.end(), unpacked.begin(), + unpacked.end()); + auto cr = detail::TransformRange{detail::ConstDereference{}, raw_v}; static_assert(std::is_same_v); static_assert(std::is_same_v); @@ -108,6 +119,13 @@ BOOST_AUTO_TEST_CASE(TransformRangeDeref) { static_assert(std::is_same_v); static_assert(std::is_same_v); checkSameAddresses(v, r); + + unpacked.clear(); + std::ranges::transform(cr, std::back_inserter(unpacked), + [](auto val) { return val; }); + + BOOST_CHECK_EQUAL_COLLECTIONS(exp.begin(), exp.end(), unpacked.begin(), + unpacked.end()); } } @@ -127,6 +145,12 @@ BOOST_AUTO_TEST_CASE(TransformRangeDeref) { static_assert(std::is_same_v); static_assert(std::is_same_v); checkSameAddresses(v, r); + + std::vector unpacked; + std::ranges::transform(r, std::back_inserter(unpacked), + [](auto val) { return val; }); + + BOOST_CHECK(unpacked == std::vector({1, 2, 3})); } std::vector raw_v; From 58a7df64411b657143248b00283c019c1829aa2f Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 10 Dec 2024 13:55:33 +0100 Subject: [PATCH 098/100] PR feedback --- Core/include/Acts/Geometry/Blueprint.hpp | 7 ++--- Core/include/Acts/Geometry/BlueprintNode.hpp | 14 +++++----- .../Acts/Geometry/BlueprintOptions.hpp | 2 -- .../CylinderContainerBlueprintNode.hpp | 10 ++++--- .../Acts/Geometry/LayerBlueprintNode.hpp | 27 ++++++++++++++----- .../Acts/Geometry/StaticBlueprintNode.hpp | 1 - Core/src/Geometry/BlueprintNode.cpp | 18 ++++++------- Core/src/Geometry/BlueprintOptions.cpp | 2 -- Core/src/Geometry/LayerBlueprintNode.cpp | 16 ----------- Examples/Python/src/Blueprint.cpp | 4 +-- Examples/Python/tests/test_blueprint.py | 2 +- Examples/Scripts/Python/blueprint.py | 2 +- .../Core/Geometry/BlueprintApiTests.cpp | 2 +- 13 files changed, 50 insertions(+), 57 deletions(-) diff --git a/Core/include/Acts/Geometry/Blueprint.hpp b/Core/include/Acts/Geometry/Blueprint.hpp index c957466601b..db96654218e 100644 --- a/Core/include/Acts/Geometry/Blueprint.hpp +++ b/Core/include/Acts/Geometry/Blueprint.hpp @@ -46,9 +46,10 @@ class GeometryContext; /// /// The construction phases are documented in @c BlueprintNode, which is the /// base class for all nodes in the tree. -/// @note This class inherits from @c BlueprintNode privately, because it is -/// only ever intended to be the top-level node, and not anywhere else in -/// the tree. +/// @note This class inherits from @c BlueprintNode, but hides the main +/// blueprint construction phase overloads. The @c Blueprint class is +/// only ever intended to be the top-level node, and not anywhere else +/// in the tree. class Blueprint : public BlueprintNode { public: struct Config { diff --git a/Core/include/Acts/Geometry/BlueprintNode.hpp b/Core/include/Acts/Geometry/BlueprintNode.hpp index 62014188baa..e159c463067 100644 --- a/Core/include/Acts/Geometry/BlueprintNode.hpp +++ b/Core/include/Acts/Geometry/BlueprintNode.hpp @@ -48,9 +48,6 @@ class LayerBlueprintNode; /// carried out. class BlueprintNode { public: - /// Can be default constructed - BlueprintNode() = default; - /// Virtual destructor to ensure correct cleanup virtual ~BlueprintNode() = default; @@ -179,11 +176,11 @@ class BlueprintNode { /// overload will invoke the constructor of @ref Acts::TrackingVolume and use /// that volume to create the node. /// @param transform The transform of the volume - /// @param volbounds The bounds of the volume + /// @param volumeBounds The bounds of the volume /// @param volumeName The name of the volume /// @param callback An optional callback that receives the node as an argument StaticBlueprintNode& addStaticVolume( - const Transform3& transform, std::shared_ptr volbounds, + const Transform3& transform, std::shared_ptr volumeBounds, const std::string& volumeName = "undefined", const std::function& callback = {}); @@ -256,11 +253,11 @@ class BlueprintNode { /// Print the node tree starting from this node to graphviz format /// @param os The stream to print to - void graphViz(std::ostream& os) const; + void graphviz(std::ostream& os) const; /// Method that writes a representatiohn of **this node only** to graphviz. /// This should generally not be called on its own, but through the @ref - /// BlueprintNode::graphViz method. + /// BlueprintNode::graphviz method. /// @param os The stream to print to virtual void addToGraphviz(std::ostream& os) const; @@ -294,4 +291,5 @@ class BlueprintNode { std::size_t m_depth{0}; std::vector> m_children{}; }; -}; // namespace Acts + +} // namespace Acts diff --git a/Core/include/Acts/Geometry/BlueprintOptions.hpp b/Core/include/Acts/Geometry/BlueprintOptions.hpp index 6e3447d9219..305ff5d399d 100644 --- a/Core/include/Acts/Geometry/BlueprintOptions.hpp +++ b/Core/include/Acts/Geometry/BlueprintOptions.hpp @@ -20,8 +20,6 @@ struct BlueprintOptions { void validate() const; - ~BlueprintOptions(); - private: static std::unique_ptr makeDefaultNavigationPolicyFactory(); diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index 5b2c54c57b5..637f1594c0c 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -28,7 +28,7 @@ namespace Acts { /// if this is not the case. class CylinderContainerBlueprintNode final : public BlueprintNode { public: - /// Main constructor for t he cylinder container node. + /// Main constructor for the cylinder container node. /// @param name The name of the node (for debug only) /// @param direction The stacking direction /// @param attachmentStrategy The attachment strategy for the stack @@ -136,11 +136,13 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { std::string m_name; - BinningValue m_direction; + BinningValue m_direction = BinningValue::binZ; - CylinderVolumeStack::AttachmentStrategy m_attachmentStrategy; + CylinderVolumeStack::AttachmentStrategy m_attachmentStrategy{ + CylinderVolumeStack::AttachmentStrategy::Midpoint}; - CylinderVolumeStack::ResizeStrategy m_resizeStrategy; + CylinderVolumeStack::ResizeStrategy m_resizeStrategy{ + CylinderVolumeStack::ResizeStrategy::Expand}; // Is only initialized during `build` std::vector m_childVolumes; diff --git a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp index 999a8272a8e..5eb2e747df8 100644 --- a/Core/include/Acts/Geometry/LayerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/LayerBlueprintNode.hpp @@ -10,7 +10,7 @@ #include "Acts/Geometry/StaticBlueprintNode.hpp" -#include +#include namespace Acts { @@ -100,6 +100,26 @@ class LayerBlueprintNode : public StaticBlueprintNode { /// @return The layer type const LayerType& layerType() const; + /// Output operator for the layer type enum. + /// @param os The output stream + /// @param type The layer type + friend std::ostream& operator<<(std::ostream& os, + LayerBlueprintNode::LayerType type) { + switch (type) { + using enum LayerBlueprintNode::LayerType; + case Cylinder: + os << "Cylinder"; + break; + case Disc: + os << "Disc"; + break; + case Plane: + os << "Plane"; + break; + } + return os; + } + private: /// @copydoc Acts::BlueprintNode::addToGraphviz void addToGraphviz(std::ostream& os) const override; @@ -118,9 +138,4 @@ class LayerBlueprintNode : public StaticBlueprintNode { LayerType m_layerType = LayerType::Cylinder; }; -/// Output operator for the layer type enum. -/// @param os The output stream -/// @param type The layer type -std::ostream& operator<<(std::ostream& os, LayerBlueprintNode::LayerType type); - } // namespace Acts diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index ca2843badc0..e30ded58491 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -37,7 +37,6 @@ class StaticBlueprintNode : public BlueprintNode { /// Build-phase of the blueprint construction. Returns the wrapped volume for /// sizing. Volume& build(const BlueprintOptions& options, const GeometryContext& gctx, - const Logger& logger = Acts::getDummyLogger()) override; /// @copydoc BlueprintNode::connect diff --git a/Core/src/Geometry/BlueprintNode.cpp b/Core/src/Geometry/BlueprintNode.cpp index f0d41f6b568..13c03495494 100644 --- a/Core/src/Geometry/BlueprintNode.cpp +++ b/Core/src/Geometry/BlueprintNode.cpp @@ -16,6 +16,7 @@ #include "Acts/Navigation/INavigationPolicy.hpp" #include "Acts/Navigation/TryAllNavigationPolicy.hpp" +#include #include namespace Acts { @@ -27,13 +28,10 @@ bool hasDescendent(const BlueprintNode& descendent, return true; } - for (const auto& child : ancestor.children()) { - if (hasDescendent(descendent, child)) { - return true; - } - } - - return false; + return std::ranges::any_of(ancestor.children(), + [&](const auto& child) -> bool { + return hasDescendent(descendent, child); + }); } } // namespace @@ -107,11 +105,11 @@ StaticBlueprintNode& BlueprintNode::addStaticVolume( } StaticBlueprintNode& BlueprintNode::addStaticVolume( - const Transform3& transform, std::shared_ptr volbounds, + const Transform3& transform, std::shared_ptr volumeBounds, const std::string& volumeName, const std::function& callback) { return addStaticVolume(std::make_unique( - transform, std::move(volbounds), volumeName), + transform, std::move(volumeBounds), volumeName), callback); } @@ -158,7 +156,7 @@ void BlueprintNode::clearChildren() { m_children.clear(); } -void BlueprintNode::graphViz(std::ostream& os) const { +void BlueprintNode::graphviz(std::ostream& os) const { os << "digraph BlueprintNode {" << std::endl; addToGraphviz(os); os << "}" << std::endl; diff --git a/Core/src/Geometry/BlueprintOptions.cpp b/Core/src/Geometry/BlueprintOptions.cpp index 4280fb24872..07913665861 100644 --- a/Core/src/Geometry/BlueprintOptions.cpp +++ b/Core/src/Geometry/BlueprintOptions.cpp @@ -26,6 +26,4 @@ BlueprintOptions::makeDefaultNavigationPolicyFactory() { .asUniquePtr(); } -BlueprintOptions::~BlueprintOptions() = default; - } // namespace Acts diff --git a/Core/src/Geometry/LayerBlueprintNode.cpp b/Core/src/Geometry/LayerBlueprintNode.cpp index ce6f1208439..de2e2cdb8cd 100644 --- a/Core/src/Geometry/LayerBlueprintNode.cpp +++ b/Core/src/Geometry/LayerBlueprintNode.cpp @@ -146,20 +146,4 @@ void LayerBlueprintNode::addToGraphviz(std::ostream& os) const { BlueprintNode::addToGraphviz(os); } -std::ostream& operator<<(std::ostream& os, LayerBlueprintNode::LayerType type) { - switch (type) { - using enum LayerBlueprintNode::LayerType; - case Cylinder: - os << "Cylinder"; - break; - case Disc: - os << "Disc"; - break; - case Plane: - os << "Plane"; - break; - } - return os; -} - } // namespace Acts diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 3d3088fd4b7..f5ce4ddc3d0 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -271,9 +271,9 @@ void addBlueprint(Context& ctx) { .def("clearChildren", &BlueprintNode::clearChildren) .def_property_readonly("name", &BlueprintNode::name) .def_property_readonly("depth", &BlueprintNode::depth) - .def("graphViz", [](BlueprintNode& self, const py::object& fh) { + .def("graphviz", [](BlueprintNode& self, const py::object& fh) { std::stringstream ss; - self.graphViz(ss); + self.graphviz(ss); fh.attr("write")(ss.str()); }); diff --git a/Examples/Python/tests/test_blueprint.py b/Examples/Python/tests/test_blueprint.py index dbaca790cb4..8471bf52105 100644 --- a/Examples/Python/tests/test_blueprint.py +++ b/Examples/Python/tests/test_blueprint.py @@ -18,7 +18,7 @@ def write(root: acts.BlueprintNode, stage: int): gz = tmp_path / f"blueprint_{stage}.dot" print(gz) with gz.open("w") as fh: - root.graphViz(fh) + root.graphviz(fh) base = acts.Transform3.Identity() diff --git a/Examples/Scripts/Python/blueprint.py b/Examples/Scripts/Python/blueprint.py index 3d516cd9b91..0dca3a6629f 100755 --- a/Examples/Scripts/Python/blueprint.py +++ b/Examples/Scripts/Python/blueprint.py @@ -84,7 +84,7 @@ with open("blueprint.dot", "w") as fh: - root.graphViz(fh) + root.graphviz(fh) gctx = acts.GeometryContext() diff --git a/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp index 513998e62c9..737f410e24b 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp @@ -357,7 +357,7 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { }); std::ofstream dot{"api_test_container.dot"}; - root->graphViz(dot); + root->graphviz(dot); auto trackingGeometry = root->construct({}, gctx, *logger); From ab8f7f9080f5d5e5d6e5c149ab829882a2c49ed1 Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 10 Dec 2024 18:32:21 +0100 Subject: [PATCH 099/100] pr feedback --- Core/include/Acts/Geometry/StaticBlueprintNode.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp index e30ded58491..f1b2b9cbd0a 100644 --- a/Core/include/Acts/Geometry/StaticBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/StaticBlueprintNode.hpp @@ -61,7 +61,7 @@ class StaticBlueprintNode : public BlueprintNode { std::unique_ptr m_shell; - std::shared_ptr m_navigationPolicyFactory = nullptr; + std::shared_ptr m_navigationPolicyFactory; }; } // namespace Acts From a99ea3af86accde614d7649b345c49fe5851b3eb Mon Sep 17 00:00:00 2001 From: Paul Gessinger Date: Tue, 10 Dec 2024 18:32:27 +0100 Subject: [PATCH 100/100] sonar fix --- Core/src/Geometry/Blueprint.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/Geometry/Blueprint.cpp b/Core/src/Geometry/Blueprint.cpp index 8d7cb56b567..f4531acaa2f 100644 --- a/Core/src/Geometry/Blueprint.cpp +++ b/Core/src/Geometry/Blueprint.cpp @@ -17,7 +17,7 @@ #include "Acts/Utilities/GraphViz.hpp" namespace { -inline static const std::string s_rootName = "Root"; +const std::string s_rootName = "Root"; } namespace Acts {