File indexing completed on 2025-04-04 07:57:59
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Geometry/GeometryIdentifierBlueprintNode.hpp"
0010
0011 #include "Acts/Geometry/BlueprintOptions.hpp"
0012 #include "Acts/Geometry/GeometryIdentifier.hpp"
0013 #include "Acts/Geometry/TrackingVolume.hpp"
0014 #include "Acts/Utilities/Logger.hpp"
0015
0016 #include <algorithm>
0017 #include <ranges>
0018
0019 #include <boost/algorithm/string/join.hpp>
0020
0021 namespace Acts::Experimental {
0022
0023 namespace {
0024 class Configuration {
0025 public:
0026 virtual ~Configuration() = default;
0027
0028 virtual void apply(const std::string& prefix, TrackingVolume& volume,
0029 const Logger& logger) = 0;
0030 virtual const std::string& name() const = 0;
0031 };
0032
0033 struct FixedLayerConfiguration : public Configuration {
0034 explicit FixedLayerConfiguration(GeometryIdentifier::Value layer)
0035 : m_layer(layer) {
0036 m_name = "GeoIdFixLayer(lay=" + std::to_string(m_layer) + ")";
0037 }
0038
0039 void apply(const std::string& prefix, TrackingVolume& volume,
0040 const Logger& logger) override {
0041 ACTS_DEBUG(prefix << "~> Setting layer to " << m_layer
0042 << " for volume with ID " << volume.geometryId());
0043 volume.assignGeometryId(volume.geometryId().withLayer(m_layer));
0044 }
0045
0046 const std::string& name() const override { return m_name; }
0047
0048 private:
0049 GeometryIdentifier::Value m_layer;
0050 std::string m_name;
0051 };
0052
0053 struct IncrementLayerConfiguration : public Configuration {
0054 explicit IncrementLayerConfiguration(GeometryIdentifier::Value start)
0055 : m_value(start) {
0056 m_name = "GeoIdIncLay(start=" + std::to_string(m_value) + ")";
0057 }
0058
0059 void apply(const std::string& prefix, TrackingVolume& volume,
0060 const Logger& logger) override {
0061 ACTS_DEBUG(prefix << "Incrementing layer component for volume with ID "
0062 << volume.geometryId());
0063 if (volume.geometryId().layer() != 0) {
0064 ACTS_ERROR("Volume " << volume.volumeName() << " already has layer ID "
0065 << volume.geometryId().layer() << ". Please check "
0066 << "your geometry configuration.");
0067 throw std::logic_error("Volume already has a layer ID");
0068 }
0069 GeometryIdentifier id = volume.geometryId().withLayer(m_value);
0070 ACTS_DEBUG(prefix << "~> Setting layer to " << m_value
0071 << " for volume with ID " << id);
0072 volume.assignGeometryId(id);
0073 m_value++;
0074 }
0075
0076 const std::string& name() const override { return m_name; }
0077
0078 private:
0079 GeometryIdentifier::Value m_value;
0080 std::string m_name;
0081 };
0082
0083 struct FixedVolumeConfiguration : public Configuration {
0084 explicit FixedVolumeConfiguration(GeometryIdentifier::Value volumeId)
0085 : m_volumeId(volumeId) {
0086 m_name = "GeoIdFixVol(vol=" + std::to_string(m_volumeId) + ")";
0087 }
0088
0089 void apply(const std::string& prefix, TrackingVolume& volume,
0090 const Logger& logger) override {
0091 ACTS_DEBUG(prefix << "~> Setting volume ID to " << m_volumeId
0092 << " for volume " << volume.volumeName()
0093 << " and all descendents");
0094 volume.apply([&](TrackingVolume& v) {
0095 if (v.geometryId().volume() != 0) {
0096 ACTS_ERROR("Volume " << v.volumeName() << " already has volume ID "
0097 << v.geometryId().volume()
0098 << ". Please check your geometry configuration.");
0099 throw std::logic_error("Volume already has a volume ID");
0100 }
0101 ACTS_DEBUG(prefix << "~> Setting volume ID to " << m_volumeId
0102 << " for volume " << v.volumeName());
0103 v.assignGeometryId(v.geometryId().withVolume(m_volumeId));
0104 });
0105 }
0106
0107 const std::string& name() const override { return m_name; }
0108
0109 private:
0110 GeometryIdentifier::Value m_volumeId;
0111 std::string m_name;
0112 };
0113
0114 }
0115
0116 struct GeometryIdentifierBlueprintNodeImpl {
0117 void add(std::unique_ptr<Configuration> configuration) {
0118 m_configurations.push_back(std::move(configuration));
0119
0120 std::vector<std::string> names;
0121 for (auto& conf : m_configurations) {
0122 names.push_back(conf->name());
0123 }
0124
0125 m_name = boost::algorithm::join(names, ", ");
0126 }
0127
0128 std::vector<std::unique_ptr<Configuration>> m_configurations;
0129 std::string m_name;
0130
0131 GeometryIdentifierBlueprintNode::CompareVolumes m_sortBy;
0132 };
0133
0134 GeometryIdentifierBlueprintNode::GeometryIdentifierBlueprintNode()
0135 : m_impl(std::make_unique<GeometryIdentifierBlueprintNodeImpl>()) {}
0136
0137 GeometryIdentifierBlueprintNode::~GeometryIdentifierBlueprintNode() = default;
0138
0139 Volume& GeometryIdentifierBlueprintNode::build(const BlueprintOptions& options,
0140 const GeometryContext& gctx,
0141 const Logger& logger) {
0142 if (children().size() != 1) {
0143 throw std::invalid_argument(
0144 "GeometryIdentifierBlueprintNode must have exactly one child");
0145 }
0146
0147 if (m_impl->m_configurations.empty()) {
0148 throw std::invalid_argument(
0149 "GeometryIdentifierBlueprintNode has no configuration");
0150 }
0151
0152 return children().at(0).build(options, gctx, logger);
0153 }
0154
0155 PortalShellBase& GeometryIdentifierBlueprintNode::connect(
0156 const BlueprintOptions& options, const GeometryContext& gctx,
0157 const Logger& logger) {
0158 return children().at(0).connect(options, gctx, logger);
0159 }
0160
0161 void GeometryIdentifierBlueprintNode::finalize(const BlueprintOptions& options,
0162 const GeometryContext& gctx,
0163 TrackingVolume& parent,
0164 const Logger& logger) {
0165 ACTS_DEBUG(prefix() << "Finalizing geo id " << name() << " with parent "
0166 << parent.volumeName());
0167 std::set<const TrackingVolume*> previous;
0168 std::ranges::for_each(parent.volumes(),
0169 [&](const auto& v) { previous.insert(&v); });
0170
0171 children().at(0).finalize(options, gctx, parent, logger);
0172
0173 std::vector<TrackingVolume*> volumes;
0174 for (auto& v : parent.volumes()) {
0175
0176
0177 if (previous.contains(&v)) {
0178 continue;
0179 }
0180
0181 volumes.push_back(&v);
0182 }
0183
0184 if (m_impl->m_sortBy) {
0185 std::ranges::sort(volumes, m_impl->m_sortBy,
0186 [](TrackingVolume* v) -> TrackingVolume& { return *v; });
0187 }
0188
0189 for (auto* volumePtr : volumes) {
0190 auto& volume = *volumePtr;
0191 ACTS_VERBOSE(
0192 prefix() << " Applying " << m_impl->m_configurations.size()
0193 << " geometry ID configuration(s) on subtree starting from "
0194 << volume.volumeName());
0195 for (auto& configuration : m_impl->m_configurations) {
0196 ACTS_VERBOSE(prefix()
0197 << "~> Applying configuration " << configuration->name());
0198 configuration->apply(prefix(), volume, logger);
0199 }
0200 ACTS_DEBUG(prefix() << "~> Final volume ID for " << volume.volumeName()
0201 << ": " << volume.geometryId());
0202 }
0203 }
0204
0205 const std::string& GeometryIdentifierBlueprintNode::name() const {
0206 return m_impl->m_name;
0207 }
0208
0209 GeometryIdentifierBlueprintNode& GeometryIdentifierBlueprintNode::setLayerIdTo(
0210 GeometryIdentifier::Value layer) {
0211 m_impl->add(std::make_unique<FixedLayerConfiguration>(layer));
0212 return *this;
0213 }
0214
0215 GeometryIdentifierBlueprintNode&
0216 GeometryIdentifierBlueprintNode::incrementLayerIds(
0217 GeometryIdentifier::Value start) {
0218 m_impl->add(std::make_unique<IncrementLayerConfiguration>(start));
0219 return *this;
0220 }
0221
0222 GeometryIdentifierBlueprintNode&
0223 GeometryIdentifierBlueprintNode::setAllVolumeIdsTo(
0224 GeometryIdentifier::Value volumeId) {
0225 m_impl->add(std::make_unique<FixedVolumeConfiguration>(volumeId));
0226 return *this;
0227 }
0228
0229 GeometryIdentifierBlueprintNode& GeometryIdentifierBlueprintNode::sortBy(
0230 const CompareVolumes& compare) {
0231 if (!compare) {
0232 throw std::invalid_argument("Invalid sorting function");
0233 }
0234 m_impl->m_sortBy = compare;
0235 return *this;
0236 }
0237
0238 }