Skip to content

Commit

Permalink
feat: introduce DD4hep Layer and Volume structure (#2505)
Browse files Browse the repository at this point in the history
This PR introduces the translation of LayerVolumes and internal
structures to the DD4hep conversion.

It adds unit tests for these for DD4hep.
  • Loading branch information
asalzburger committed Oct 10, 2023
1 parent d8c447c commit 09ac8b6
Show file tree
Hide file tree
Showing 12 changed files with 846 additions and 9 deletions.
4 changes: 3 additions & 1 deletion Plugins/DD4hep/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ add_library(
src/DD4hepDetectorElement.cpp
src/DD4hepDetectorSurfaceFactory.cpp
src/DD4hepLayerBuilder.cpp
src/DD4hepVolumeBuilder.cpp)
src/DD4hepLayerStructure.cpp
src/DD4hepVolumeBuilder.cpp
src/DD4hepVolumeStructure.cpp)
target_include_directories(
ActsPluginDD4hep
PUBLIC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

#pragma once

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Definitions/Common.hpp"

#include <DD4hep/DetElement.h>
#include <DD4hep/DetFactoryHelper.h>
#include <DD4hep/Objects.h>
Expand Down Expand Up @@ -117,7 +120,7 @@ value_type getAttrValueOr(const dd4hep::xml::Component& node,
///
/// @tparam value_type the primitive type allowed by variant parameters
///
/// @param dd4hepElement the detector element w
/// @param dd4hepElement the detector element with associated variant parameters
/// @param bname The base name attribute of the variant parameter pack
/// @param unitConversion is a conversion factor DD4hep -> ACTS
///
Expand All @@ -140,4 +143,25 @@ std::vector<value_type> extractSeries(const dd4hep::DetElement& dd4hepElement,
return series;
}

/// @brief A simple helper function to extract a transform
///
/// @param dd4hepElement the detector element with associated variant parameters
/// @param bname The base name attribute of the variant parameter pack
/// @param unitConversion is a conversion factor DD4hep -> ACTS
///
/// @return a transform extracted from parameters
inline Transform3 extractTransform(const dd4hep::DetElement& dd4hepElement,
const std::string& bname,
const ActsScalar unitConversion = 1.) {
Transform3 transform = Transform3::Identity();
ActsScalar x =
unitConversion * getParamOr<ActsScalar>(bname + "_x", dd4hepElement, 0.);
ActsScalar y =
unitConversion * getParamOr<ActsScalar>(bname + "_y", dd4hepElement, 0.);
ActsScalar z =
unitConversion * getParamOr<ActsScalar>(bname + "_z", dd4hepElement, 0.);
transform.pretranslate(Vector3(x, y, z));
return transform;
}

} // namespace Acts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// 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/Definitions/Units.hpp"
#include "Acts/Detector/LayerStructureBuilder.hpp"
#include "Acts/Detector/ProtoBinning.hpp"
#include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp"
#include "Acts/Plugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp"
#include "Acts/Utilities/Logger.hpp"

#include <memory>
#include <string>

namespace dd4hep {
class DetElement;
}

namespace Acts {

namespace Experimental {

/// @brief This class allows to generate layer structure builders for dd4hep sub detectors
/// It performs an intermediate step by taking dd4hep::DetElemnent objects that
/// describe a detector structure and prepares the translation of the detector
/// element and eventual passive surfaces.
///
/// It would also build passive support structures if configured to do so.
///
class DD4hepLayerStructure {
public:
/// Constructor with DD4hepDetectorSurfaceFactory
///
/// @param surfaceFactory the surfac factory which converts dd4hep::DetElement objects
/// into their Acts coutnerparts
/// @param logger is the screen output logger
///
/// @note this needs to be provided
DD4hepLayerStructure(
std::shared_ptr<DD4hepDetectorSurfaceFactory> surfaceFactory,
std::unique_ptr<const Logger> logger =
getDefaultLogger("DD4hepLayerStructure", Acts::Logging::INFO));

DD4hepLayerStructure() = delete;

/// @brief Nested options struct
///
/// If a binning description or a support cylinder
/// description is chosen through options, it overwrites the corresponding
/// description coming from DD4hep.
struct Options {
/// The name of the object
std::string name = "";
/// An out put log level
Logging::Level logLevel = Logging::INFO;
/// Approximation for the polyhedron binning nSegments
unsigned int nSegments = 1u;
/// Conversion options
DD4hepDetectorSurfaceFactory::Options conversionOptions;
};

/// @brief This method generates a LayerStructure builder, which extends the
/// IInternalStructureBuilder and can be used in the conjunction with a
/// IExternalStructureBuilder to create `DetectorVolume` objects.
///
/// It takes the detector element from DD4hep and some optional parameters
///
/// @param dd4hepStore [in, out] the detector store for the built elements
/// @param dd4hepElement the dd4hep detector element
/// @param options containing the optional descriptions
///
/// @return a LayerStructureBuilder
std::shared_ptr<LayerStructureBuilder> builder(
DD4hepDetectorElement::Store& dd4hepStore,
const dd4hep::DetElement& dd4hepElement, const Options& options) const;

private:
/// The workorse: the surface factory
std::shared_ptr<DD4hepDetectorSurfaceFactory> m_surfaceFactory = nullptr;

/// Logging instance
std::unique_ptr<const Logger> m_logger;

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

} // namespace Experimental
} // namespace Acts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// 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/Definitions/Units.hpp"
#include "Acts/Detector/VolumeStructureBuilder.hpp"
#include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp"
#include "Acts/Utilities/Logger.hpp"

#include <memory>
#include <string>

#include <DD4hep/DD4hepUnits.h>

namespace dd4hep {
class DetElement;
}

namespace Acts {

namespace Experimental {

/// @brief This class allows to generate volumes structure builders for dd4hep sub detectors,
/// together with an internal structure builder, this is sufficient to build the
/// new DetectorVolume objects.
///
class DD4hepVolumeStructure {
public:
/// Constructor with arguments
/// @param mlogger is the screen output logger
DD4hepVolumeStructure(std::unique_ptr<const Logger> mlogger =
getDefaultLogger("DD4hepVolumeStructure",
Acts::Logging::INFO));

DD4hepVolumeStructure() = delete;

/// @brief nested options struct
///
/// If a binning description or a support cylinder
/// description is chosen through options, it overwrites the corresponding
/// description coming from DD4hep.
struct Options {
/// The name of the object
std::string name = "";
/// An output log level for the builder
Acts::Logging::Level logLevel = Acts::Logging::INFO;
};

/// @brief This method generates a VolumeStructureBuilder, which extends the
/// IExternalStructureBuilder to create `DetectorVolume` objects.
///
/// It takes the detector element from DD4hep and some optional parameters
///
/// @param dd4hepElement the dd4hep detector element
/// @param options containing the optional descriptions
///
/// @return a VolumeStructureBuilder
std::shared_ptr<VolumeStructureBuilder> builder(
const dd4hep::DetElement& dd4hepElement, const Options& options) const;

private:
/// @brief auto-calculate the unit length conversion
static constexpr ActsScalar unitLength =
Acts::UnitConstants::mm / dd4hep::millimeter;

/// @brief Method to recursively parse through the detector element
/// and grep the volume structure information
///
/// @param vsbConfig
/// @param dd4hepElement
///
/// @return a boolean break condition
bool recursiveParse(VolumeStructureBuilder::Config& vsbConfig,
const dd4hep::DetElement& dd4hepElement) const;

/// Logging instance
std::unique_ptr<const Logger> m_logger;

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

} // namespace Experimental
} // namespace Acts
98 changes: 98 additions & 0 deletions Plugins/DD4hep/src/DD4hepLayerStructure.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// 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/.

#include "Acts/Plugins/DD4hep/DD4hepLayerStructure.hpp"

Acts::Experimental::DD4hepLayerStructure::DD4hepLayerStructure(
std::shared_ptr<DD4hepDetectorSurfaceFactory> surfaceFactory,
std::unique_ptr<const Logger> logger)
: m_surfaceFactory(std::move(surfaceFactory)), m_logger(std::move(logger)) {
if (m_surfaceFactory == nullptr) {
throw std::invalid_argument(
"DD4hepLayerStructure: no surface factory provided");
}
}

std::shared_ptr<Acts::Experimental::LayerStructureBuilder>
Acts::Experimental::DD4hepLayerStructure::builder(
DD4hepDetectorElement::Store& dd4hepStore,
const dd4hep::DetElement& dd4hepElement, const Options& options) const {
// Check for misconfiguration with double naming
if (dd4hepStore.find(options.name) != dd4hepStore.end()) {
std::string reMessage = "DD4hepLayerStructure: structure with name '";
reMessage += options.name;
reMessage += "' already registered in DetectorElementStore";
throw std::runtime_error(reMessage.c_str());
}

// This object is going to be filled with the created surfaces
DD4hepDetectorSurfaceFactory::Cache fCache;
m_surfaceFactory->construct(fCache, dd4hepElement, options.conversionOptions);

ACTS_DEBUG("Conversion from DD4Hep : " << fCache.sensitiveSurfaces.size()
<< " sensitive surfaces");

ACTS_DEBUG("Conversion from DD4Hep : " << fCache.passiveSurfaces.size()
<< " passive surfaces");

// Check if binning was provided or detected
if (fCache.binnings.empty() and
(fCache.sensitiveSurfaces.size() + fCache.passiveSurfaces.size()) > 0u) {
ACTS_VERBOSE(
"Surface binning neither provided nor found, navigation will be "
"'tryAll' (could result in slow navigation).");
}

// Surfaces are prepared for creating the builder
LayerStructureBuilder::Config lsbConfig;
lsbConfig.auxiliary = "*** DD4hep driven builder for: ";
lsbConfig.auxiliary += options.name;
// Translate binings and supports
lsbConfig.binnings = fCache.binnings;
lsbConfig.supports = fCache.supports;

std::vector<std::shared_ptr<Surface>> lSurfaces;
lSurfaces.reserve(fCache.sensitiveSurfaces.size() +
fCache.passiveSurfaces.size());

std::vector<std::shared_ptr<DD4hepDetectorElement>> cElements;
cElements.reserve(fCache.sensitiveSurfaces.size());

// Fill them in to the surface provider struct and detector store
for (auto [de, ds] : fCache.sensitiveSurfaces) {
lSurfaces.push_back(ds);
cElements.push_back(de);
}
dd4hepStore[options.name] = cElements;

// Passive surfaces to be added
for (auto [ps, toAll] : fCache.passiveSurfaces) {
// Passive surface is not declared to be added to all navigation bins
if (not toAll) {
lSurfaces.push_back(ps);
} else {
// Passive surface is indeed declared to be added to all navigaiton bins
Experimental::ProtoSupport pSupport;
pSupport.surface = ps;
pSupport.assignToAll = true;
lsbConfig.supports.push_back(pSupport);
}
}

lsbConfig.surfacesProvider =
std::make_shared<Experimental::LayerStructureBuilder::SurfacesHolder>(
lSurfaces);

ACTS_DEBUG("Configured with " << lsbConfig.binnings.size() << " binnings.");
ACTS_DEBUG("Configured to build " << lsbConfig.supports.size()
<< " supports.");

// Return the structure builder
return std::make_shared<LayerStructureBuilder>(
lsbConfig, getDefaultLogger(options.name, options.logLevel));
}

0 comments on commit 09ac8b6

Please sign in to comment.