Skip to content

Commit

Permalink
feat: Geometry ID Generator aka ODD light part3 (acts-project#2462)
Browse files Browse the repository at this point in the history
This PR introduces:

- an interface of a `Acts::Experimental::IGeometryIdGenerator` tool
- a standard `Acts::Experimental::GeometryIdGenerator` implementation
- slots in the detector building to attach those generators
- a check in the `Acts::Detector` class that surfaces have unique geometry ids
- a `Acts::GeometryHierarchyMap<Surface>` for the detector
- unit tests for all of those
- finally the ODD light with geometry id settings as the ODD standard

This is a squashed version of acts-project#2439 -  It sits on top of acts-project#2424 and acts-project#2436 and will wait until those are merged.
  • Loading branch information
asalzburger authored and AJPfleger committed Sep 29, 2023
1 parent 38996e4 commit 5005848
Show file tree
Hide file tree
Showing 30 changed files with 930 additions and 30 deletions.
5 changes: 5 additions & 0 deletions Core/include/Acts/Detector/CylindricalContainerBuilder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace Acts {
namespace Experimental {

class IRootVolumeFinderBuilder;
class IGeometryIdGenerator;

/// @brief A dedicated container builder for cylindrical detector containers
///
Expand All @@ -45,6 +46,10 @@ class CylindricalContainerBuilder : public IDetectorComponentBuilder {
std::vector<BinningValue> binning = {};
/// The root volume finder
std::shared_ptr<IRootVolumeFinderBuilder> rootVolumeFinderBuilder = nullptr;
/// The geometry id generator
std::shared_ptr<const IGeometryIdGenerator> geoIdGenerator = nullptr;
/// An eventual reverse geometry id generation
bool geoIdReverseGen = false;
/// Auxiliary information, mainly for screen output
std::string auxiliary = "";
};
Expand Down
13 changes: 13 additions & 0 deletions Core/include/Acts/Detector/Detector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "Acts/Definitions/Common.hpp"
#include "Acts/Detector/DetectorVolume.hpp"
#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Geometry/GeometryHierarchyMap.hpp"
#include "Acts/Geometry/GeometryIdentifier.hpp"
#include "Acts/Navigation/NavigationDelegates.hpp"
#include "Acts/Utilities/Delegate.hpp"

Expand All @@ -23,6 +25,9 @@
#include <vector>

namespace Acts {

class Surface;

namespace Experimental {
struct NavigationState;

Expand Down Expand Up @@ -90,6 +95,11 @@ class Detector : public std::enable_shared_from_this<Detector> {
/// @return a vector to const DetectorVolume raw pointers
const std::vector<const DetectorVolume*>& volumes() const;

/// Const access to the hierarchy map of all sensitive surfaces
///
/// @return the map which can be queried with GeometryID for ranges
const GeometryHierarchyMap<const Surface*>& sensitiveHierarchyMap() const;

/// Update the current volume of a given navigation state
///
/// @param gctx is the Geometry context of the call
Expand Down Expand Up @@ -142,6 +152,9 @@ class Detector : public std::enable_shared_from_this<Detector> {

/// Name/index map to find volumes by name and detect duplicates
std::unordered_map<std::string, size_t> m_volumeNameIndex;

/// Geometry Id hierarchy map of all sensitive surfaces
GeometryHierarchyMap<const Surface*> m_sensitiveHierarchyMap;
};

} // namespace Experimental
Expand Down
4 changes: 4 additions & 0 deletions Core/include/Acts/Detector/DetectorBuilder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
namespace Acts {
namespace Experimental {

class IGeometryIdGenerator;

/// @brief Standard generic Detector builder that calls
/// the top level component builder and transfers the
/// result into a detector object
Expand All @@ -33,6 +35,8 @@ class DetectorBuilder final : public IDetectorBuilder {
std::string name = "unnamed";
/// An external builder
std::shared_ptr<const IDetectorComponentBuilder> builder = nullptr;
/// A geometry id generator
std::shared_ptr<const IGeometryIdGenerator> geoIdGenerator = nullptr;
/// Auxiliary information
std::string auxiliary = "";
};
Expand Down
6 changes: 6 additions & 0 deletions Core/include/Acts/Detector/DetectorVolume.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,12 @@ class DetectorVolume : public std::enable_shared_from_this<DetectorVolume> {
/// @return the geometry identifier
const GeometryIdentifier& geometryId() const;

/// Set the geometry identifier
/// @note no checking is done, it will overwrite any existing id
///
/// @param geoID is the geometry Id that is set to the object
void assignGeometryId(const GeometryIdentifier& geoID);

/// Assign Detector to this volume (for back navigation issues)
/// @param detector the parenting detector class
void assignDetector(const Detector& detector);
Expand Down
3 changes: 3 additions & 0 deletions Core/include/Acts/Detector/DetectorVolumeBuilder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace Acts {
namespace Experimental {
class IExternalStructureBuilder;
class IInternalStructureBuilder;
class IGeometryIdGenerator;

/// @brief A generic detector volume builder that uses
/// an external builder for shape and portals and an internal
Expand All @@ -41,6 +42,8 @@ class DetectorVolumeBuilder : public IDetectorComponentBuilder {
std::shared_ptr<const IExternalStructureBuilder> externalsBuilder = nullptr;
/// An internal builder
std::shared_ptr<const IInternalStructureBuilder> internalsBuilder = nullptr;
/// The geometry id generator
std::shared_ptr<const IGeometryIdGenerator> geoIdGenerator = nullptr;
/// Add eventual internal volume to root
bool addInternalsToRoot = false;
/// Auxiliary information
Expand Down
125 changes: 125 additions & 0 deletions Core/include/Acts/Detector/GeometryIdGenerator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// This file is part of the Acts project.
//
// Copyright (C) 2023 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 http://mozilla.org/MPL/2.0/.

#pragma once

#include "Acts/Detector/interface/IGeometryIdGenerator.hpp"
#include "Acts/Geometry/GeometryIdentifier.hpp"
#include "Acts/Utilities/Logger.hpp"

#include <any>

namespace Acts {

class Surface;

namespace Experimental {

class Portal;
class DetectorVolume;

/// @brief This is the default implementation of the geometry id generator
///
/// It is a simple counter based generator that assigns ids to the geometry
/// and increments the counter for each object type.
///
/// Sub counters, i.e. for the sensitive surfaces, are reset after the volume
/// call, such that a new volume or layer volume would start from counter 0
/// again.
///
/// If the generator is configured to override existing ids, it will do so
/// and not respect previously assigned ids.
///
/// If the generator is configured in container mode, it will increase the
/// layer id for each layer volume with confined surfaces.
///
class GeometryIdGenerator final : public IGeometryIdGenerator {
public:
/// @brief Nested config struct
struct Config {
/// Container mode
bool containerMode = false;
/// Container id (if container mode), will not be incremented
unsigned int containerId = 0u;
/// Resetting mode
bool resetSubCounters = true;
/// Force override existing ids
bool overrideExistingIds = false;
};

/// @brief Nested cache struct
struct Cache {
/// Cache count of the volume, for non-container mode
unsigned int volumeCount = 0u;
/// Cache count of the layer volume, for container mode
unsigned int layerCount = 0u;
/// Cache count of the portal surfaces
unsigned int portalCount = 0u;
/// Cache count of passive surfaces
unsigned int passiveCount = 0u;
/// Cache count of sensitive surfaces
unsigned int sensitiveCount = 0u;
};

/// @brief Constructor with config
///
/// @param cfg is the geometry configuration object
/// @param mlogger is the logging instance
GeometryIdGenerator(const Config& cfg,
std::unique_ptr<const Logger> mlogger = getDefaultLogger(
"GeometryIdGenerator", Logging::INFO))
: m_cfg(cfg), m_logger(std::move(mlogger)) {}

~GeometryIdGenerator() override = default;

/// @brief Interface method to generata a geometry id cache
/// @return a geometry id cache decorated in a std::any object
IGeometryIdGenerator::GeoIdCache generateCache() const final;

/// @brief Method for assigning a geometry id to a detector volume
///
/// @param cache is the cache object for e.g. object counting
/// @param dVolume the detector volume to assign the geometry id to
void assignGeometryId(IGeometryIdGenerator::GeoIdCache& cache,
DetectorVolume& dVolume) const final;

/// @brief Method for assigning a geometry id to a portal
///
/// @param cache is the cache object for e.g. object counting
/// @param portal the portal to assign the geometry id to
void assignGeometryId(IGeometryIdGenerator::GeoIdCache& cache,
Portal& portal) const final;

/// @brief Method for assigning a geometry id to a surface
///
/// @param cache is the cache object for e.g. object counting
/// @param surface the surface to assign the geometry id to
void assignGeometryId(IGeometryIdGenerator::GeoIdCache& cache,
Surface& surface) const final;

private:
/// @brief Helper method to get the volume id from the cache
///
/// @param cache the provided cache
/// @param incrementLayer if true, the layer counter is incremented
///
/// @return a valid geometry identifier
GeometryIdentifier volumeId(Cache& cache, bool incrementLayer = true) const;

/// Configuration object
Config m_cfg;

/// Private access method to the logger
const Logger& logger() const { return *m_logger; }

/// logging instance
std::unique_ptr<const Logger> m_logger;
};

} // namespace Experimental
} // namespace Acts
59 changes: 59 additions & 0 deletions Core/include/Acts/Detector/interface/IGeometryIdGenerator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// This file is part of the Acts project.
//
// Copyright (C) 2023 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 http://mozilla.org/MPL/2.0/.

#pragma once

#include <any>

namespace Acts {

class Surface;

namespace Experimental {

class Portal;
class DetectorVolume;

/// @brief This is the interface for generating geometry ids and assign them
/// to detector volumes, portals and surfaces
///
class IGeometryIdGenerator {
public:
using GeoIdCache = std::any;

virtual ~IGeometryIdGenerator() = default;

/// @brief Virtual interface method to generata a geometry id cache
/// @return a geometry id cache decorated in a std::any object
virtual GeoIdCache generateCache() const = 0;

/// The virtual interface definition for assigning a geometry id to
/// a detector volume
///
/// @param cache is the cache object for e.g. object counting
/// @param dVolume the detector volume to assign the geometry id to
virtual void assignGeometryId(GeoIdCache& cache,
DetectorVolume& dVolume) const = 0;

/// The virtual interface definition for assigning a geometry id to
/// a portal
///
/// @param cache is the cache object for e.g. object counting
/// @param portal the portal to assign the geometry id to
virtual void assignGeometryId(GeoIdCache& cache, Portal& portal) const = 0;

/// @brief The virtual interface definition for assigning a geometry id to
/// a surface
///
/// @param cache is the cache object for e.g. object counting
/// @param surface the surface to assign the geometry id to
virtual void assignGeometryId(GeoIdCache& cache, Surface& surface) const = 0;
};

} // namespace Experimental
} // namespace Acts
7 changes: 7 additions & 0 deletions Core/include/Acts/Geometry/GeometryIdentifier.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class GeometryIdentifier {
constexpr Value layer() const { return getBits(kLayerMask); }
/// Return the approach identifier.
constexpr Value approach() const { return getBits(kApproachMask); }
/// Return the approach identifier.
constexpr Value passive() const { return getBits(kApproachMask); }
/// Return the sensitive identifier.
constexpr Value sensitive() const { return getBits(kSensitiveMask); }
/// Return the extra identifier
Expand All @@ -76,6 +78,10 @@ class GeometryIdentifier {
constexpr GeometryIdentifier& setApproach(Value approach) {
return setBits(kApproachMask, approach);
}
/// Set the approach identifier - shared with Passive
constexpr GeometryIdentifier& setPassive(Value approach) {
return setBits(kApproachMask, approach);
}
/// Set the sensitive identifier.
constexpr GeometryIdentifier& setSensitive(Value sensitive) {
return setBits(kSensitiveMask, sensitive);
Expand All @@ -95,6 +101,7 @@ class GeometryIdentifier {
static constexpr Value kLayerMask = 0x0000fff000000000;
/// (2^8)-1 = 255 approach surfaces
static constexpr Value kApproachMask = 0x0000000ff0000000;
static constexpr Value kPassiveMask = kApproachMask;
/// (2^20)-1 = 1048575 sensitive surfaces
static constexpr Value kSensitiveMask = 0x000000000fffff00;
/// (2^8)-1 = 255 extra values
Expand Down
1 change: 1 addition & 0 deletions Core/src/Detector/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ target_sources(
Portal.cpp
PortalGenerators.cpp
ProtoDetector.cpp
GeometryIdGenerator.cpp
VolumeStructureBuilder.cpp
MultiWireStructureBuilder.cpp

Expand Down
16 changes: 16 additions & 0 deletions Core/src/Detector/CylindricalContainerBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "Acts/Detector/DetectorComponents.hpp"
#include "Acts/Detector/detail/CylindricalDetectorHelper.hpp"
#include "Acts/Detector/interface/IGeometryIdGenerator.hpp"
#include "Acts/Detector/interface/IRootVolumeFinderBuilder.hpp"
#include "Acts/Navigation/DetectorVolumeFinders.hpp"

Expand Down Expand Up @@ -166,6 +167,21 @@ Acts::Experimental::CylindricalContainerBuilder::construct(
m_cfg.rootVolumeFinderBuilder->construct(gctx, rootVolumes)}};
}

// Geometry Id generation
if (m_cfg.geoIdGenerator != nullptr) {
ACTS_DEBUG("Assigning geometry ids to the detector");
auto cache = m_cfg.geoIdGenerator->generateCache();
if (m_cfg.geoIdReverseGen) {
std::for_each(rootVolumes.rbegin(), rootVolumes.rend(), [&](auto& v) {
m_cfg.geoIdGenerator->assignGeometryId(cache, *v);
});
} else {
std::for_each(rootVolumes.begin(), rootVolumes.end(), [&](auto& v) {
m_cfg.geoIdGenerator->assignGeometryId(cache, *v);
});
}
}

// Return the container
return Acts::Experimental::DetectorComponent{
{}, rContainer, RootDetectorVolumes{rootVolumes, tryRootVolumes()}};
Expand Down
Loading

0 comments on commit 5005848

Please sign in to comment.