-
Notifications
You must be signed in to change notification settings - Fork 173
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 |
---|---|---|
@@ -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); | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -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> | ||||||||||||||||||||||||||||||||||||
|
@@ -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))); | ||||||||||||||||||||||||||||||||||||
Comment on lines
+48
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Handle decorator initialization failures, wise one must. Hmmmm. Protect against initialization failures of alignment decorator, we should. Validate configuration before proceeding, essential it is. DD4hepAlignmentDecorator::Config dd4hepAcfg;
dd4hepAcfg.nominal = m_nominal;
dd4hepAcfg.trackingGeometry = dd4tGeometry;
+ if (!dd4hepAcfg.trackingGeometry) {
+ throw std::runtime_error{"Invalid tracking geometry in alignment decorator configuration"};
+ }
ContextDecorators dd4ContextDecorators = {};
dd4ContextDecorators.push_back(std::make_shared<DD4hepAlignmentDecorator>(
std::move(dd4hepAcfg),
Acts::getDefaultLogger("AlignmentDecorator", Acts::Logging::INFO))); 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||
std::cout << "After dd4ContextDecorators push back" << std::endl; | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use proper logging mechanism, you must. std::cout, a path to the dark side it is. Replace direct console output with proper logging framework, we should. - std::cout << "After dd4ContextDecorators push back" << std::endl;
+ ACTS_DEBUG("Alignment decorator successfully initialized"); 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||
// return the pair of geometry and empty decorators | ||||||||||||||||||||||||||||||||||||
return std::make_pair<TrackingGeometryPtr, ContextDecorators>( | ||||||||||||||||||||||||||||||||||||
std::move(dd4tGeometry), std::move(dd4ContextDecorators)); | ||||||||||||||||||||||||||||||||||||
|
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 |
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()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+19
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Error handling wisdom, share I must. Consider adding error handling for invalid transformations: 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()) {
+ // Validate transformation matrix
+ if (!it->second.matrix().allFinite()) {
+ throw std::runtime_error("Invalid transformation matrix for detector element " +
+ std::to_string(dElement.identifier()));
+ }
return it->second;
} else {
return dElement.nominalTransform(DD4hepGeometryContext());
}
} else {
return dElement.nominalTransform(DD4hepGeometryContext());
}
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void Acts::DD4hepGeometryContext::setAlignmentStore( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
std::unordered_map<std::string, Transform3> alignmentStore) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
m_alignmentStore = alignmentStore; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Exception throwing you do, but more detail helpful it may be.
When surfaces are null or not alignable, an invalid_argument is thrown. Additional context about which surface triggers the error, wise it would be to include.