Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding features for traccc data production #2845

Merged
merged 14 commits into from
Dec 20, 2023
98 changes: 98 additions & 0 deletions Core/include/Acts/Detector/GeometryIdGenerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,103 @@ class GeometryIdGenerator final : public IGeometryIdGenerator {
std::unique_ptr<const Logger> m_logger;
};

/// This is a chained tgeometry id generator that will be in seuqnce
/// @tparam generators_t the gnernerators that will be called in sequence
asalzburger marked this conversation as resolved.
Show resolved Hide resolved
///
/// @note the generators are expected to be move constructable
asalzburger marked this conversation as resolved.
Show resolved Hide resolved
/// and of pointer type
template <typename... generators_t>
class ChainedGeometryIdGenerator : public IGeometryIdGenerator {
public:
struct Cache {
/// The caches
std::array<IGeometryIdGenerator::GeoIdCache, sizeof...(generators_t)>
storage;
};

/// The stored generators
std::tuple<generators_t...> generators;

/// Constructor for chained generators_t in a tuple, this will unroll
/// the tuple and call them in sequence
///
/// @param gens the updators to be called in chain
/// @param mlogger is the logging instance
ChainedGeometryIdGenerator(const std::tuple<generators_t...>&& gens,
std::unique_ptr<const Logger> mlogger =
getDefaultLogger("ChainedGeometryIdGenerator",
Logging::INFO))
: generators(std::move(gens)), m_logger(std::move(mlogger)) {}

/// @brief Interface method to generata a geometry id cache
/// @return a geometry id cache decorated in a std::any object
asalzburger marked this conversation as resolved.
Show resolved Hide resolved
IGeometryIdGenerator::GeoIdCache generateCache() const final {
// Unfold the tuple and add the attachers
Cache cache;
std::size_t it = 0;
std::apply(
[&](auto&&... generator) {
((cache.storage[it++] = generator->generateCache()), ...);
},
generators);
return cache;
}

/// @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 {
ACTS_VERBOSE("Assigning chained geometry id to volume.");
assign(cache, dVolume);
}

/// @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 {
ACTS_VERBOSE("Assigning chained geometry id to portal.");
assign(cache, portal);
}

/// @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 {
ACTS_VERBOSE("Assigning chained geometry id to surface.");
assign(cache, surface);
}

private:
/// @brief Helper to run through the chain of generators
///
/// @tparam gometry_object_t the geometry object type
///
/// @param the cache object with the array of sub caches
/// @param object the object to assign the geometry id to
template <typename gometry_object_t>
void assign(IGeometryIdGenerator::GeoIdCache& cache,
gometry_object_t& object) const {
std::size_t it = 0;
auto& sCache = std::any_cast<Cache&>(cache);
std::apply(
[&](auto&&... generator) {
(generator->assignGeometryId(sCache.storage[it++], object), ...);
},
generators);
}

/// 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
141 changes: 141 additions & 0 deletions Core/include/Acts/Detector/GeometryIdMapper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// This file is part of the Acts project.
//
// Copyright (C) 2017-2018 CERN for the benefit of the Acts project
asalzburger marked this conversation as resolved.
Show resolved Hide resolved
//
// 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/DetectorVolume.hpp"
#include "Acts/Detector/Portal.hpp"
#include "Acts/Detector/interface/IGeometryIdGenerator.hpp"
#include "Acts/Geometry/GeometryIdentifier.hpp"
#include "Acts/Surfaces/Surface.hpp"

#include <map>

namespace Acts {
namespace Experimental {

/// @brief This is a mapper of geometry ids, which can be used to
/// assign predefined geometry ids to objects
///
/// The only requirement is that the source identifier can be established
/// from the object that receives the target geometry id itself.
template <typename SourceIdentifier, typename SourceCapture>
class GeometryIdMapper final : public IGeometryIdGenerator {
public:
/// @brief Nested config struct
struct Config {
/// The source identifier to target geometry Id map
std::map<SourceIdentifier, GeometryIdentifier> sourceTargetMap;
/// The source capture function
asalzburger marked this conversation as resolved.
Show resolved Hide resolved
SourceCapture sourceCapture = SourceCapture();
};

/// @brief Cache object
struct Cache {
unsigned int volumeCounter = 0;
unsigned int portalCounter = 0;
unsigned int surfaceCounter = 0;
};

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

~GeometryIdMapper() override = default;

/// @brief Interface method to generata a geometry id cache
/// @return a geometry id cache decorated in a std::any object
asalzburger marked this conversation as resolved.
Show resolved Hide resolved
IGeometryIdGenerator::GeoIdCache generateCache() const final {
return Cache{0};
asalzburger marked this conversation as resolved.
Show resolved Hide resolved
}

/// @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 {
auto& sCache = std::any_cast<Cache&>(cache);
/// Retrieve the source id for the detector volume
SourceIdentifier vID = m_cfg.sourceCapture(dVolume);
auto source = m_cfg.sourceTargetMap.find(vID);
if (source != m_cfg.sourceTargetMap.end()) {
dVolume.assignGeometryId(source->second);
ACTS_VERBOSE("Assigning geometry id " << source->second << " to volume "
<< dVolume.name() << " with id "
<< vID);
sCache.volumeCounter++;
}

// Portals
std::for_each(dVolume.portalPtrs().begin(), dVolume.portalPtrs().end(),
[&](auto& portal) { assignGeometryId(cache, *portal); });

// Surfaces
std::for_each(dVolume.surfacePtrs().begin(), dVolume.surfacePtrs().end(),
[&](auto& surface) { assignGeometryId(cache, *surface); });

// Sub volumes
std::for_each(dVolume.volumePtrs().begin(), dVolume.volumePtrs().end(),
[&](auto& volume) { assignGeometryId(cache, *volume); });
}

/// @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 {
auto& sCache = std::any_cast<Cache&>(cache);
/// Retrieve the source id for the portal
SourceIdentifier pID = m_cfg.sourceCapture(portal);
auto source = m_cfg.sourceTargetMap.find(pID);
if (source != m_cfg.sourceTargetMap.end()) {
portal.surface().assignGeometryId(source->second);
ACTS_VERBOSE("Assigning geometry id " << source->second << " to portal "
<< " with id " << pID);
sCache.portalCounter++;
}
}

/// @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 {
auto& sCache = std::any_cast<Cache&>(cache);
/// Retrieve the source id for the surface
SourceIdentifier sID = m_cfg.sourceCapture(surface);
auto source = m_cfg.sourceTargetMap.find(sID);
if (source != m_cfg.sourceTargetMap.end()) {
ACTS_VERBOSE("Assigning geometry id " << source->second << " to surface "
<< " with id " << sID);
surface.assignGeometryId(source->second);
sCache.surfaceCounter++;
}
}

private:
/// 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
71 changes: 71 additions & 0 deletions Examples/Python/src/DD4hepComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 http://mozilla.org/MPL/2.0/.

#include "Acts/Detector/GeometryIdGenerator.hpp"
#include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp"
#include "Acts/Plugins/DD4hep/DD4hepDetectorStructure.hpp"
#include "Acts/Plugins/DD4hep/DD4hepFieldAdapter.hpp"
#include "Acts/Plugins/DD4hep/DD4hepIdentifierMapper.hpp"
#include "Acts/Plugins/Python/Utilities.hpp"
#include "Acts/Utilities/Logger.hpp"
#include "ActsExamples/DD4hepDetector/DD4hepDetector.hpp"
#include "ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp"
#include "ActsExamples/Framework/IContextDecorator.hpp"
Expand Down Expand Up @@ -69,6 +72,39 @@ PYBIND11_MODULE(ActsPythonBindingsDD4hep, m) {
m, "DD4hepDetectorElement");
}

{
m.def("createDD4hepIdGeoIdMap",
[](const Acts::TrackingGeometry& tGeometry)
-> std::map<Acts::DD4hepDetectorElement::DD4hepVolumeID,
Acts::GeometryIdentifier> {
// The surface visitor
struct DD4hepIdGrabber {
std::map<Acts::DD4hepDetectorElement::DD4hepVolumeID,
Acts::GeometryIdentifier>
dd4hepIdGeoIdMap;

void operator()(const Acts::Surface* surface) {
const auto* dde = surface->associatedDetectorElement();
const auto* dd4hepDetElement =
dynamic_cast<const Acts::DD4hepDetectorElement*>(dde);
// Check if it is valid
if (dd4hepDetElement) {
dd4hep::DDSegmentation::VolumeID dd4hepID =
dd4hepDetElement->sourceElement().volumeID();
auto geoID = surface->geometryId();
dd4hepIdGeoIdMap[dd4hepID] = geoID;
}
}
};

// Create an instance
DD4hepIdGrabber dd4hepIdGrabber;
// Visit the surfaces & return what you have
tGeometry.visitSurfaces(dd4hepIdGrabber);
return dd4hepIdGrabber.dd4hepIdGeoIdMap;
});
}

{
using Options = Acts::Experimental::DD4hepDetectorStructure::Options;
auto o = py::class_<Options>(m, "DD4hepDetectorOptions").def(py::init<>());
Expand All @@ -78,6 +114,41 @@ PYBIND11_MODULE(ActsPythonBindingsDD4hep, m) {
ACTS_PYTHON_STRUCT_END();

patchKwargsConstructor(o);

m.def(
"attachDD4hepGeoIdMapper",
[](Acts::Experimental::DD4hepDetectorStructure::Options& options,
const std::map<Acts::DD4hepDetectorElement::DD4hepVolumeID,
Acts::GeometryIdentifier>& dd4hepIdGeoIdMap) {
// The Geo mapper
auto geoIdMapper =
std::make_shared<const Acts::DD4hepIdentifierMapper>(
Acts::DD4hepIdentifierMapper::Config{dd4hepIdGeoIdMap},
Acts::getDefaultLogger("GeometryIdMapper", options.logLevel));

// A remaining recursive logger
auto geoIdGenerator =
std::make_shared<const Acts::Experimental::GeometryIdGenerator>(
Acts::Experimental::GeometryIdGenerator::Config{},
Acts::getDefaultLogger("GeometryIdGenerator",
options.logLevel));

std::tuple<
std::shared_ptr<const Acts::Experimental::GeometryIdGenerator>,
std::shared_ptr<const Acts::DD4hepIdentifierMapper>>
chainedGenerators = {geoIdGenerator, geoIdMapper};

auto chainedGeoIdGenerator = std::make_shared<
const Acts::Experimental::ChainedGeometryIdGenerator<
std::shared_ptr<
const Acts::Experimental::GeometryIdGenerator>,
std::shared_ptr<const Acts::DD4hepIdentifierMapper>>>(
std::move(chainedGenerators),
Acts::getDefaultLogger("ChainedGeometryIdGenerator",
options.logLevel));

options.geoIdGenerator = chainedGeoIdGenerator;
});
}

{
Expand Down
3 changes: 2 additions & 1 deletion Examples/Python/src/Geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ void addGeometry(Context& ctx) {
.def("boundary", &Acts::GeometryIdentifier::boundary)
.def("approach", &Acts::GeometryIdentifier::approach)
.def("sensitive", &Acts::GeometryIdentifier::sensitive)
.def("extra", &Acts::GeometryIdentifier::extra);
.def("extra", &Acts::GeometryIdentifier::extra)
.def("value", &Acts::GeometryIdentifier::value);
}

{
Expand Down
24 changes: 23 additions & 1 deletion Examples/Scripts/Python/detector_creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
DD4hepGeometryService,
)

import json

from common import getOpenDataDetectorDirectory

Expand All @@ -24,7 +25,28 @@
dd4hepGeometryService = DD4hepGeometryService(dd4hepConfig)
dd4hepDetector = DD4hepDetector(dd4hepGeometryService)

cOptions = DD4hepDetectorOptions(logLevel=acts.logging.VERBOSE, emulateToGraph="")

# Uncomment if you want to use the geometry id mapping
# This map can be produced with the 'geometry.py' script
geoIdMappingFile = None # 'odd-dd4hep-geoid-mapping.json'
if geoIdMappingFile is not None:
# Load the geometry id mapping json file
with open(geoIdMappingFile) as f:
# load the file as is
geometry_id_mapping = json.load(f)
# create a dictionary with GeometryIdentifier as value
geometry_id_mapping_patched = {
int(k): acts.GeometryIdentifier(int(v))
for k, v in geometry_id_mapping.items()
}
# patch the options struct
acts.examples.dd4hep.attachDD4hepGeoIdMapper(
cOptions, geometry_id_mapping_patched
)

# Context and options
geoContext = acts.GeometryContext()
cOptions = DD4hepDetectorOptions(logLevel=acts.logging.INFO, emulateToGraph="")
[detector, contextors, store] = dd4hepDetector.finalize(geoContext, cOptions)

acts.examples.writeDetectorToJsonDetray(geoContext, detector, "odd-detray.json")
Loading
Loading