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

add misalignment decoration for DD4hep detector #3891

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Examples/Detectors/DD4hepDetector/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_library(
SHARED
src/DD4hepDetector.cpp
src/DD4hepGeometryService.cpp
src/DD4hepAlignmentDecorator.cpp
)

target_include_directories(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#pragma once

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp"
#include "Acts/Utilities/Logger.hpp"
#include "ActsExamples/Framework/AlgorithmContext.hpp"
#include "ActsExamples/Framework/IContextDecorator.hpp"
#include "ActsExamples/Framework/ProcessCode.hpp"
#include "ActsExamples/Framework/RandomNumbers.hpp"
#include <Acts/Geometry/TrackingGeometry.hpp>

#include <cstddef>
#include <iostream>
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>

namespace ActsExamples {
struct AlgorithmContext;

namespace DD4hep {
class DD4hepAlignmentDecorator : public IContextDecorator {
public:
using LayerStore = std::vector<std::shared_ptr<Acts::DD4hepDetectorElement>>;
using DetectorStore = std::vector<LayerStore>;
struct Config {
// whether use the nominal geometry
bool nominal = true;
// path of Json file which is used to store the misalignment matrix of each
// detector element
// @todo use `JsonMisalignmentConfig`
std::string misAlignedGeoJsonPath = "odd-misalignment-matrix.json";
// tracking geometry
std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry = nullptr;
};

DD4hepAlignmentDecorator(const Config& cfg,
std::unique_ptr<const Acts::Logger> logger =
Acts::getDefaultLogger("AlignmentDecorator",
Acts::Logging::INFO));
~DD4hepAlignmentDecorator() override = default;
ProcessCode decorate(AlgorithmContext& context) override;
const std::string& name() const override { return m_name; }

private:
Config m_cfg; ///< the configuration class
std::unique_ptr<const Acts::Logger> m_logger; ///!< the logging instance
const Acts::Logger& logger() const { return *m_logger; }
std::string m_name = "Aligned Detector";
std::unordered_map<std::string, Acts::Transform3>
m_misalignmentAtConstruction;
std::unordered_map<std::string, Acts::Transform3> m_nominalStore;
std::unordered_map<std::string, Acts::Transform3> m_mistransform;
void parseGeometry(const Acts::TrackingGeometry& tGeometry);
void initializeMisFromJson(const std::string& misAlignedGeoJsonFile);
};

inline void DD4hepAlignmentDecorator::initializeMisFromJson(
const std::string& misJson) {
std::ifstream file(misJson);
if (!file.is_open())
throw std::runtime_error("Unable to open file");
nlohmann::json jsonData;
file >> jsonData;
for (auto& [key, value] : jsonData.items()) {
if (value.is_array() && value.size() == 6) {
double x = value[0].get<double>();
double y = value[1].get<double>();
double z = value[2].get<double>();
double alpha = value[3].get<double>() / 180 * M_PI;
double beta = value[4].get<double>() / 180 * M_PI;
double gamma = value[5].get<double>() / 180 * M_PI;
Acts::Transform3 translation =
Eigen::Affine3d(Eigen::Translation3d(x, y, z));
Acts::Transform3 delta_rotationx =
Eigen::Affine3d(Eigen::AngleAxisd(alpha, Eigen::Vector3d::UnitX()));
Acts::Transform3 delta_rotationy =
Eigen::Affine3d(Eigen::AngleAxisd(beta, Eigen::Vector3d::UnitY()));
Acts::Transform3 delta_rotationz =
Eigen::Affine3d(Eigen::AngleAxisd(gamma, Eigen::Vector3d::UnitZ()));
m_misalignmentAtConstruction[key] =
translation * delta_rotationx * delta_rotationy * delta_rotationz;
}
}
std::cout << "Successfully initialize the JSON file" << std::endl;
}
} // namespace DD4hep
} // namespace ActsExamples
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ struct DD4hepDetector {
/// @brief Access to the DD4hep field
/// @return a shared pointer to the DD4hep field
std::shared_ptr<Acts::DD4hepFieldAdapter> field() const;

// whether use the nominal geometry
bool m_nominal = false;
};

} // namespace ActsExamples::DD4hep
82 changes: 82 additions & 0 deletions Examples/Detectors/DD4hepDetector/src/DD4hepAlignmentDecorator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// 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 "ActsExamples/DD4hepDetector/DD4hepAlignmentDecorator.hpp"

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp"
#include "Acts/Plugins/DD4hep/DD4hepGeometryContext.hpp"
#include "ActsExamples/Framework/AlgorithmContext.hpp"
#include "ActsExamples/Framework/RandomNumbers.hpp"
#include <Acts/Geometry/TrackingGeometry.hpp>

#include <ostream>
#include <thread>
#include <utility>

ActsExamples::DD4hep::DD4hepAlignmentDecorator::DD4hepAlignmentDecorator(
const Config& cfg, std::unique_ptr<const Acts::Logger> logger)
: m_cfg(cfg), m_logger(std::move(logger)) {
if (m_cfg.trackingGeometry != nullptr) {
parseGeometry(*m_cfg.trackingGeometry.get());
}
}

ActsExamples::ProcessCode
ActsExamples::DD4hep::DD4hepAlignmentDecorator::decorate(
AlgorithmContext& context) {
Acts::DD4hepGeometryContext dd4hepGeoCtx =
Acts::DD4hepGeometryContext(m_cfg.nominal);
if (!m_cfg.nominal) {
initializeMisFromJson(m_cfg.misAlignedGeoJsonPath);
for (const auto& entry : m_misalignmentAtConstruction) {
const std::string& identifier = entry.first;
const Acts::Transform3& misalignmentTransform = entry.second;
auto nominalIt = m_nominalStore.find(identifier);
if (nominalIt != m_nominalStore.end()) {
const Acts::Transform3& nominalTransform = nominalIt->second;
Eigen::Matrix3d R1 = nominalTransform.rotation();
Eigen::Vector3d T1 = nominalTransform.translation();
Eigen::Matrix3d R2 = misalignmentTransform.rotation();
Eigen::Vector3d T2 = misalignmentTransform.translation();
Eigen::Matrix3d R3 = R1 * R2;
Eigen::Vector3d T3 = T1 + T2;
m_mistransform[identifier] =
Eigen::Affine3d(Eigen::Translation3d(T3)) * Eigen::Affine3d(R3);
}
}
dd4hepGeoCtx.setAlignmentStore(m_mistransform);
}
context.geoContext = dd4hepGeoCtx;
return ProcessCode::SUCCESS;
}

void ActsExamples::DD4hep::DD4hepAlignmentDecorator::parseGeometry(
const Acts::TrackingGeometry& tGeometry) {
// Double-visit - first count
std::size_t nTransforms = 0;
tGeometry.visitSurfaces([&nTransforms](const auto*) { ++nTransforms; });
std::unordered_map<std::string, Acts::Transform3> aStore;
Acts::GeometryContext nominalCtx = {};
// Collect the surfacas into the nominal store
auto fillTransforms = [&aStore, &nominalCtx](const auto* surface) -> void {
if (surface == nullptr) {
throw std::invalid_argument("Surface is nullptr.");
}
auto alignableElement = dynamic_cast<const Acts::DD4hepDetectorElement*>(
surface->associatedDetectorElement());
if (alignableElement == nullptr) {
throw std::invalid_argument("Surface is not alignable");
}
unsigned long long id = alignableElement->identifier();
aStore[Form("%lld", id)] = surface->transform(nominalCtx);
};
tGeometry.visitSurfaces(fillTransforms);
m_nominalStore = std::move(aStore);
}
9 changes: 9 additions & 0 deletions Examples/Detectors/DD4hepDetector/src/DD4hepDetector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/MagneticField/MagneticFieldProvider.hpp"
#include "Acts/Plugins/DD4hep/DD4hepFieldAdapter.hpp"
#include "ActsExamples/DD4hepDetector/DD4hepAlignmentDecorator.hpp"
#include "ActsExamples/DD4hepDetector/DD4hepGeometryService.hpp"

#include <cstddef>
Expand Down Expand Up @@ -43,7 +44,15 @@ auto DD4hepDetector::finalize(
throw std::runtime_error{
"Did not receive tracking geometry from DD4hep geometry service"};
}

DD4hepAlignmentDecorator::Config dd4hepAcfg;
dd4hepAcfg.nominal = m_nominal;
dd4hepAcfg.trackingGeometry = dd4tGeometry;
ContextDecorators dd4ContextDecorators = {};
dd4ContextDecorators.push_back(std::make_shared<DD4hepAlignmentDecorator>(
std::move(dd4hepAcfg),
Acts::getDefaultLogger("AlignmentDecorator", Acts::Logging::INFO)));
std::cout << "After dd4ContextDecorators push back" << std::endl;
// return the pair of geometry and empty decorators
return std::make_pair<TrackingGeometryPtr, ContextDecorators>(
std::move(dd4tGeometry), std::move(dd4ContextDecorators));
Expand Down
1 change: 1 addition & 0 deletions Plugins/DD4hep/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ add_library(
src/DD4hepDetectorStructure.cpp
src/DD4hepMaterialHelpers.cpp
src/DD4hepDetectorElement.cpp
src/DD4hepGeometryContext.cpp
src/DD4hepDetectorSurfaceFactory.cpp
src/DD4hepLayerBuilder.cpp
src/DD4hepLayerStructure.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#pragma once

#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Plugins/DD4hep/DD4hepGeometryContext.hpp"
#include "Acts/Plugins/TGeo/TGeoDetectorElement.hpp"
#include "Acts/Utilities/ThrowAssert.hpp"

Expand Down Expand Up @@ -87,6 +88,11 @@ class DD4hepDetectorElement : public TGeoDetectorElement {
// Give access to the DD4hep detector element
const dd4hep::DetElement& sourceElement() const { return m_detElement; }

const Transform3& transform(const GeometryContext& gctx) const override;
Transform3 nominalTransform(const GeometryContext& gctx) const {
return TGeoDetectorElement::transform(gctx);
}

private:
/// DD4hep detector element
dd4hep::DetElement m_detElement;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// This file is part of the ACTS project.
//
// Copyright (C) 2016-2024 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/Definitions/Algebra.hpp"
#include "Acts/Geometry/GeometryContext.hpp"

#include <nlohmann/json.hpp>

namespace Acts {

class DD4hepDetectorElement;

/// @class GeometryContext
///
/// @brief DD4hep specific geometry context for alignment handling
///
/// Extends the base GeometryContext to provide DD4hep-specific alignment
/// capabilities. The context can be active or inactive, controlling whether
/// alignment corrections should be applied.
///
/// @note This context is specifically designed to work with DD4hepDetectorElement
/// and provides contextual transformations for alignment purposes.
///
class DD4hepGeometryContext : public GeometryContext {
public:
using AlignmentStore = std::unordered_map<std::string, Transform3>;

/// Default constructor
DD4hepGeometryContext() = default;

/// Constructor
explicit DD4hepGeometryContext(bool isGeometryNominal)
: m_nominal(isGeometryNominal) {}

/// The transform of this detector element within the given context
///
/// @param dElement The detector element
///
/// @return The transform of the detector element
const Transform3& contextualTransform(
const DD4hepDetectorElement& dElement) const;

void setAlignmentStore(
std::unordered_map<std::string, Transform3> alignmentStore);

/// @brief Return the active status of the context
/// @return boolean that indicates if the context is active
bool isNominal() const { return m_nominal; }

private:
bool m_nominal = true;
AlignmentStore m_alignmentStore = {};
};

} // namespace Acts
13 changes: 13 additions & 0 deletions Plugins/DD4hep/src/DD4hepDetectorElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

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

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

#include <iostream>
#include <utility>

#include <DD4hep/Alignments.h>
Expand All @@ -23,3 +26,13 @@ Acts::DD4hepDetectorElement::DD4hepDetectorElement(
detElement.nominal().worldTransformation(), axes, scalor,
std::move(material)),
m_detElement(detElement) {}

const Acts::Transform3& Acts::DD4hepDetectorElement::transform(
const GeometryContext& gctx) const {
const Acts::DD4hepGeometryContext* dd4hepGtx =
gctx.maybeGet<DD4hepGeometryContext>();
if (dd4hepGtx != nullptr && !dd4hepGtx->isNominal()) {
return dd4hepGtx->contextualTransform(*this);
}
return TGeoDetectorElement::transform(gctx);
}
36 changes: 36 additions & 0 deletions Plugins/DD4hep/src/DD4hepGeometryContext.cpp
Original file line number Diff line number Diff line change
@@ -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/Plugins/DD4hep/DD4hepGeometryContext.hpp"

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

#include <iostream>

#include <nlohmann/json.hpp>

const Acts::Transform3& Acts::DD4hepGeometryContext::contextualTransform(
const DD4hepDetectorElement& dElement) const {
if (!this->isNominal()) {
auto it = m_alignmentStore.find(Form("%lld", dElement.identifier()));
if (it != m_alignmentStore.end()) {
return it->second;
} else {
return dElement.nominalTransform(DD4hepGeometryContext());
}
} else {
return dElement.nominalTransform(DD4hepGeometryContext());
}
}

void Acts::DD4hepGeometryContext::setAlignmentStore(
std::unordered_map<std::string, Transform3> alignmentStore) {
m_alignmentStore = alignmentStore;
}
Loading