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: GeoModel changes for Gen1 ITk #3685

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
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/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ add_subdirectory(GenericDetector)
add_subdirectory_if(Geant4Detector ACTS_BUILD_EXAMPLES_GEANT4)
add_subdirectory(MagneticField)
add_subdirectory(TGeoDetector)
add_subdirectory(ITkModuleSplitting)
add_subdirectory(TelescopeDetector)
add_subdirectory_if(MuonSpectrometerMockupDetector ACTS_BUILD_EXAMPLES_GEANT4)
7 changes: 7 additions & 0 deletions Examples/Detectors/ITkModuleSplitting/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
add_library(ActsExamplesITkModuleSplitting INTERFACE)
target_include_directories(
ActsExamplesITkModuleSplitting
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)

install(DIRECTORY include/ActsExamples DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// 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/.

// This file is part of the Acts project.
//
// Copyright (C) 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 http://mozilla.org/MPL/2.0/.

#pragma once

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Surfaces/AnnulusBounds.hpp"
#include "Acts/Surfaces/RectangleBounds.hpp"
#include "Acts/Surfaces/Surface.hpp"
#include "Acts/Surfaces/SurfaceBounds.hpp"

#include <algorithm>
#include <array>
#include <cstddef>
#include <sstream>

namespace ActsExamples::ITk {

template <typename detector_element_t, typename element_factory_t>
inline std::vector<std::shared_ptr<const detector_element_t>> splitBarrelModule(
const Acts::GeometryContext& gctx,
const std::shared_ptr<const detector_element_t>& detElement,
unsigned int nSegments, const element_factory_t& factory,
const std::string& name,
const Acts::Logger& logger = Acts::getDummyLogger()) {
// Retrieve the surface
const Acts::Surface& surface = detElement->surface();
const Acts::SurfaceBounds& bounds = surface.bounds();
if (bounds.type() != Acts::SurfaceBounds::eRectangle || nSegments <= 1u) {
ACTS_WARNING("Invalid splitting config for barrel node: "
<< name << "! Node will not be slpit.");
return {detElement};
}

// Output container for the submodules
std::vector<std::shared_ptr<const detector_element_t>> detElements = {};
detElements.reserve(nSegments);

// Get the geometric information
const Acts::Transform3& transform = surface.transform(gctx);
// Determine the new bounds
const std::vector<double> boundsValues = bounds.values();

double lengthX = (boundsValues[Acts::RectangleBounds::eMaxX] -
boundsValues[Acts::RectangleBounds::eMinX]) /
nSegments;
double lengthY = boundsValues[Acts::RectangleBounds::eMaxY] -
boundsValues[Acts::RectangleBounds::eMinY];
auto rectBounds =
std::make_shared<Acts::RectangleBounds>(0.5 * lengthX, 0.5 * lengthY);
// Translation for every subelement
auto localTranslation = Acts::Vector2(-0.5 * lengthX * (nSegments - 1), 0.);
const auto step = Acts::Vector2(lengthX, 0.);
ACTS_DEBUG("Rectangle bounds for new node (half length): " +
std::to_string(rectBounds->halfLengthX()) + ", " +
std::to_string(rectBounds->halfLengthY()));

for (std::size_t i = 0; i < nSegments; i++) {
Acts::Vector3 globalTranslation =
surface.localToGlobal(gctx, localTranslation, {}) -
transform.translation();
auto elemTransform =
Acts::Transform3(transform).pretranslate(globalTranslation);
detElements.emplace_back(factory(elemTransform, rectBounds));

localTranslation += step;
}
return detElements;
}

template <typename detector_element_t, typename element_factory_t>
inline std::vector<std::shared_ptr<detector_element_t>> splitDiscModule(
const Acts::GeometryContext& gctx,
const std::shared_ptr<detector_element_t>& detElement,
const std::vector<std::pair<double, double>>& splitRanges,
const element_factory_t& factory, const std::string& name,
const Acts::Logger& logger = Acts::getDummyLogger()) {
// Retrieve the surface
const Acts::Surface& surface = detElement->surface();
const Acts::SurfaceBounds& bounds = surface.bounds();

// Check annulus bounds origin
auto printOrigin = [&](const Acts::Surface& sf) {
Acts::Vector3 discOrigin =
sf.localToGlobal(gctx, Acts::Vector2(0., 0.), Acts::Vector3::Zero());
std::string out =
"Disc surface origin at: " + std::to_string(discOrigin[0]) + ", " +
std::to_string(discOrigin[1]) + ", " + std::to_string(discOrigin[2]);
return out;
};
ACTS_DEBUG(printOrigin(surface));

if (bounds.type() != Acts::SurfaceBounds::eAnnulus || splitRanges.empty()) {
ACTS_WARNING("Invalid splitting config for disk node: "
<< name << "! Node will not be slpit.");
return {detElement};
}

auto nSegments = splitRanges.size();

// Output container for the submodules
std::vector<std::shared_ptr<const detector_element_t>> detElements = {};
detElements.reserve(nSegments);

// Get the geometric information
const Acts::Transform3& transform = surface.transform(gctx);
const std::vector<double> boundsValues = bounds.values();
std::array<double, Acts::AnnulusBounds::eSize> values{};

std::copy_n(boundsValues.begin(), Acts::AnnulusBounds::eSize, values.begin());

for (std::size_t i = 0; i < nSegments; i++) {
if (boundsValues[Acts::AnnulusBounds::eMinR] > splitRanges[i].first ||
boundsValues[Acts::AnnulusBounds::eMaxR] < splitRanges[i].second) {
ACTS_WARNING(
"Radius pattern not within the original bounds, node will not be "
"split!");
return {detElement};
}

values[Acts::AnnulusBounds::eMinR] = splitRanges[i].first;
values[Acts::AnnulusBounds::eMaxR] = splitRanges[i].second;
auto annulusBounds = std::make_shared<Acts::AnnulusBounds>(values);
ACTS_DEBUG(
"New r bounds for node: " + std::to_string(annulusBounds->rMin()) +
", " + std::to_string(annulusBounds->rMax()));

auto element = factory(transform, annulusBounds);
detElements.push_back(std::move(element));
}
return detElements;
}

} // namespace ActsExamples::ITk
1 change: 1 addition & 0 deletions Examples/Detectors/TGeoDetector/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ target_link_libraries(
ActsPluginJson
ActsExamplesFramework
ActsExamplesDetectorGeneric
ActsExamplesITkModuleSplitting
)

install(
Expand Down
113 changes: 18 additions & 95 deletions Examples/Detectors/TGeoDetector/src/TGeoITkModuleSplitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@
#include "Acts/Surfaces/RectangleBounds.hpp"
#include "Acts/Surfaces/Surface.hpp"
#include "Acts/Surfaces/SurfaceBounds.hpp"
#include "ActsExamples/ITkModuleSplitting/ITkModuleSplitting.hpp"

#include <algorithm>
#include <array>
#include <cstddef>
#include <sstream>

namespace {}

benjaminhuth marked this conversation as resolved.
Show resolved Hide resolved
ActsExamples::TGeoITkModuleSplitter::TGeoITkModuleSplitter(
const ActsExamples::TGeoITkModuleSplitter::Config& cfg,
std::unique_ptr<const Acts::Logger> logger)
Expand Down Expand Up @@ -86,55 +89,16 @@ ActsExamples::TGeoITkModuleSplitter::splitBarrelModule(
const Acts::GeometryContext& gctx,
const std::shared_ptr<const Acts::TGeoDetectorElement>& detElement,
unsigned int nSegments) const {
// Retrieve the surface
auto identifier = detElement->identifier();
const Acts::Surface& surface = detElement->surface();
const Acts::SurfaceBounds& bounds = surface.bounds();
if (bounds.type() != Acts::SurfaceBounds::eRectangle || nSegments <= 1u) {
ACTS_WARNING("Invalid splitting config for barrel node: " +
std::string(detElement->tgeoNode().GetName()) +
"! Node will not be slpit.");
return {detElement};
}

// Output container for the submodules
std::vector<std::shared_ptr<const Acts::TGeoDetectorElement>> detElements =
{};
detElements.reserve(nSegments);

// Get the geometric information
double thickness = detElement->thickness();
const Acts::Transform3& transform = surface.transform(gctx);
// Determine the new bounds
const std::vector<double> boundsValues = bounds.values();
double lengthX = (boundsValues[Acts::RectangleBounds::eMaxX] -
boundsValues[Acts::RectangleBounds::eMinX]) /
nSegments;
double lengthY = boundsValues[Acts::RectangleBounds::eMaxY] -
boundsValues[Acts::RectangleBounds::eMinY];
auto rectBounds =
std::make_shared<Acts::RectangleBounds>(0.5 * lengthX, 0.5 * lengthY);
// Translation for every subelement
auto localTranslation = Acts::Vector2(-0.5 * lengthX * (nSegments - 1), 0.);
const auto step = Acts::Vector2(lengthX, 0.);
ACTS_DEBUG("Rectangle bounds for new node (half length): " +
std::to_string(rectBounds->halfLengthX()) + ", " +
std::to_string(rectBounds->halfLengthY()));
auto name = detElement->tgeoNode().GetName();

for (std::size_t i = 0; i < nSegments; i++) {
Acts::Vector3 globalTranslation =
surface.localToGlobal(gctx, localTranslation, {}) -
transform.translation();
auto elemTransform =
Acts::Transform3(transform).pretranslate(globalTranslation);
auto element = std::make_shared<const Acts::TGeoDetectorElement>(
identifier, detElement->tgeoNode(), elemTransform, rectBounds,
thickness);
detElements.push_back(std::move(element));
auto factory = [&](const auto& trafo, const auto& bounds) {
return std::make_shared<const Acts::TGeoDetectorElement>(
detElement->identifier(), detElement->tgeoNode(), trafo, bounds,
detElement->thickness());
};

localTranslation += step;
}
return detElements;
return ITk::splitBarrelModule(gctx, detElement, nSegments, factory, name,
logger());
}

/// If applicable, returns a split detector element
Expand All @@ -144,55 +108,14 @@ ActsExamples::TGeoITkModuleSplitter::splitDiscModule(
const std::shared_ptr<const Acts::TGeoDetectorElement>& detElement,
const std::vector<ActsExamples::TGeoITkModuleSplitter::SplitRange>&
splitRanges) const {
// Retrieve the surface
auto identifier = detElement->identifier();
const Acts::Surface& surface = detElement->surface();
const Acts::SurfaceBounds& bounds = surface.bounds();
auto name = detElement->tgeoNode().GetName();

// Check annulus bounds origin
auto printOrigin = [&](const Acts::Surface& sf) {
Acts::Vector3 discOrigin =
sf.localToGlobal(gctx, Acts::Vector2(0., 0.), Acts::Vector3::Zero());
std::string out =
"Disc surface origin at: " + std::to_string(discOrigin[0]) + ", " +
std::to_string(discOrigin[1]) + ", " + std::to_string(discOrigin[2]);
return out;
auto factory = [&](const auto& trafo, const auto& bounds) {
return std::make_shared<const Acts::TGeoDetectorElement>(
detElement->identifier(), detElement->tgeoNode(), trafo, bounds,
detElement->thickness());
};
ACTS_DEBUG(printOrigin(surface));

if (bounds.type() != Acts::SurfaceBounds::eAnnulus || splitRanges.empty()) {
ACTS_WARNING("Invalid splitting config for disk node: " +
std::string(detElement->tgeoNode().GetName()) +
"! Node will not be slpit.");
return {detElement};
}

auto nSegments = splitRanges.size();

// Output container for the submodules
std::vector<std::shared_ptr<const Acts::TGeoDetectorElement>> detElements =
{};
detElements.reserve(nSegments);

// Get the geometric information
double thickness = detElement->thickness();
const Acts::Transform3& transform = surface.transform(gctx);
const std::vector<double> boundsValues = bounds.values();
std::array<double, Acts::AnnulusBounds::eSize> values{};
std::copy_n(boundsValues.begin(), Acts::AnnulusBounds::eSize, values.begin());

for (std::size_t i = 0; i < nSegments; i++) {
values[Acts::AnnulusBounds::eMinR] = splitRanges[i].first;
values[Acts::AnnulusBounds::eMaxR] = splitRanges[i].second;
auto annulusBounds = std::make_shared<Acts::AnnulusBounds>(values);
ACTS_DEBUG(
"New r bounds for node: " + std::to_string(annulusBounds->rMin()) +
", " + std::to_string(annulusBounds->rMax()));

auto element = std::make_shared<const Acts::TGeoDetectorElement>(
identifier, detElement->tgeoNode(), transform, annulusBounds,
thickness);
detElements.push_back(std::move(element));
}
return detElements;
return ITk::splitDiscModule(gctx, detElement, splitRanges, factory, name,
logger());
}
Loading
Loading