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

refactor(geo): Teach ProtoLayer to respect local coordinate system #3697

Merged
Merged
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
32 changes: 30 additions & 2 deletions Core/include/Acts/Geometry/ProtoLayer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ struct ProtoLayer {
/// The envelope parameters
ExtentEnvelope envelope = ExtentEnvelope::Zero();

/// The local transform
Transform3 transform = Transform3::Identity();

/// Constructor
///
/// Loops over a provided vector of surface and calculates the various
Expand All @@ -41,8 +44,10 @@ struct ProtoLayer {
///
/// @param gctx The current geometry context object, e.g. alignment
/// @param surfaces The vector of surfaces to consider
/// @param transformIn The local transform to evaluate the sizing in
ProtoLayer(const GeometryContext& gctx,
const std::vector<const Surface*>& surfaces);
const std::vector<const Surface*>& surfaces,
const Transform3& transformIn = Transform3::Identity());

/// Constructor
///
Expand All @@ -52,8 +57,23 @@ struct ProtoLayer {
///
/// @param gctx The current geometry context object, e.g. alignment
/// @param surfaces The vector of surfaces to consider
/// @param transformIn The local transform to evaluate the sizing in
ProtoLayer(const GeometryContext& gctx,
const std::vector<std::shared_ptr<const Surface>>& surfaces);
const std::vector<std::shared_ptr<const Surface>>& surfaces,
const Transform3& transformIn = Transform3::Identity());

/// Constructor
///
/// Loops over a provided vector of surface and calculates the various
/// min/max values in one go. Also takes into account the thickness
/// of an associated DetectorElement, if it exists.
///
/// @param gctx The current geometry context object, e.g. alignment
/// @param surfaces The vector of surfaces to consider
/// @param transformIn The local transform to evaluate the sizing in
ProtoLayer(const GeometryContext& gctx,
const std::vector<std::shared_ptr<Surface>>& surfaces,
const Transform3& transformIn = Transform3::Identity());

ProtoLayer() = default;

Expand Down Expand Up @@ -81,6 +101,14 @@ struct ProtoLayer {
/// @param sl the input ostream
std::ostream& toStream(std::ostream& sl) const;

/// Output stream operator
/// @param sl the input ostream
/// @param pl the ProtoLayer to be printed
/// @return the output ostream
friend std::ostream& operator<<(std::ostream& sl, const ProtoLayer& pl) {
return pl.toStream(sl);
}

/// Give access to the surfaces used/assigned to the ProtoLayer
const std::vector<const Surface*>& surfaces() const;

Expand Down
34 changes: 20 additions & 14 deletions Core/src/Geometry/ProtoLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,34 @@
#include "Acts/Surfaces/RegularSurface.hpp"
#include "Acts/Utilities/Helpers.hpp"

#include <algorithm>
#include <array>
#include <string>
#include <utility>

using Acts::VectorHelpers::perp;
using Acts::VectorHelpers::phi;

namespace Acts {

ProtoLayer::ProtoLayer(const GeometryContext& gctx,
const std::vector<const Surface*>& surfaces)
: m_surfaces(surfaces) {
const std::vector<const Surface*>& surfaces,
const Transform3& transformIn)
: transform(transformIn), m_surfaces(surfaces) {
measure(gctx, surfaces);
}

ProtoLayer::ProtoLayer(
const GeometryContext& gctx,
const std::vector<std::shared_ptr<const Surface>>& surfaces)
: m_surfaces(unpack_shared_vector(surfaces)) {
const std::vector<std::shared_ptr<const Surface>>& surfaces,
const Transform3& transformIn)
: transform(transformIn), m_surfaces(unpack_shared_vector(surfaces)) {
measure(gctx, m_surfaces);
}

ProtoLayer::ProtoLayer(const GeometryContext& gctx,
const std::vector<std::shared_ptr<Surface>>& surfaces,
const Transform3& transformIn)
: transform(transformIn) {
m_surfaces.reserve(surfaces.size());
for (const auto& sf : surfaces) {
m_surfaces.push_back(sf.get());
}
measure(gctx, m_surfaces);
}

Expand Down Expand Up @@ -78,15 +86,13 @@ void ProtoLayer::measure(const GeometryContext& gctx,
double thickness = element->thickness();
// We need a translation along and opposite half thickness
Vector3 sfNormal = regSurface->normal(gctx, sf->center(gctx));
std::vector<double> deltaT = {-0.5 * thickness, 0.5 * thickness};
for (const auto& dT : deltaT) {
Transform3 dtransform = Transform3::Identity();
dtransform.pretranslate(dT * sfNormal);
for (const auto& dT : {-0.5 * thickness, 0.5 * thickness}) {
Transform3 dtransform = transform * Translation3{dT * sfNormal};
extent.extend(sfPolyhedron.extent(dtransform));
}
continue;
}
extent.extend(sfPolyhedron.extent());
extent.extend(sfPolyhedron.extent(transform));
}
}

Expand Down
161 changes: 134 additions & 27 deletions Tests/UnitTests/Core/Geometry/ProtoLayerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,33 @@
#include <boost/test/unit_test.hpp>

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Definitions/Units.hpp"
#include "Acts/Geometry/DetectorElementBase.hpp"
#include "Acts/Geometry/Extent.hpp"
#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Geometry/ProtoLayer.hpp"
#include "Acts/Surfaces/PlaneSurface.hpp"
#include "Acts/Surfaces/RectangleBounds.hpp"
#include "Acts/Surfaces/Surface.hpp"
#include "Acts/Tests/CommonHelpers/DetectorElementStub.hpp"
#include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
#include "Acts/Utilities/BinningType.hpp"
#include "Acts/Utilities/RangeXD.hpp"

#include <array>
#include <cmath>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

namespace Acts::Test::Layers {

GeometryContext tgContext = GeometryContext();

BOOST_AUTO_TEST_SUITE(Geometry)

BOOST_AUTO_TEST_CASE(ProtoLayerTests) {
GeometryContext tgContext = GeometryContext();
using enum BinningValue;

// Create a proto layer with 4 surfaces on the x/y grid
auto recBounds = std::make_shared<RectangleBounds>(3., 6.);
Expand Down Expand Up @@ -105,20 +108,20 @@ BOOST_AUTO_TEST_CASE(ProtoLayerTests) {
// Test 1 - identity transform
auto protoLayer = createProtoLayer(Transform3::Identity());

CHECK_CLOSE_ABS(protoLayer.range(BinningValue::binX), 12., 1e-8);
CHECK_CLOSE_ABS(protoLayer.medium(BinningValue::binX), 0., 1e-8);
CHECK_CLOSE_ABS(protoLayer.min(BinningValue::binX), -6., 1e-8);
CHECK_CLOSE_ABS(protoLayer.max(BinningValue::binX), 6., 1e-8);
CHECK_CLOSE_ABS(protoLayer.range(BinningValue::binY), 6., 1e-8);
CHECK_CLOSE_ABS(protoLayer.medium(BinningValue::binY), 0., 1e-8);
CHECK_CLOSE_ABS(protoLayer.min(BinningValue::binY), -3., 1e-8);
CHECK_CLOSE_ABS(protoLayer.max(BinningValue::binY), 3., 1e-8);
CHECK_CLOSE_ABS(protoLayer.range(BinningValue::binZ), 12., 1e-8);
CHECK_CLOSE_ABS(protoLayer.medium(BinningValue::binZ), 0., 1e-8);
CHECK_CLOSE_ABS(protoLayer.min(BinningValue::binZ), -6., 1e-8);
CHECK_CLOSE_ABS(protoLayer.max(BinningValue::binZ), 6., 1e-8);
CHECK_CLOSE_ABS(protoLayer.max(BinningValue::binR), std::hypot(3, 6), 1e-8);
CHECK_CLOSE_ABS(protoLayer.min(BinningValue::binR), 3., 1e-8);
CHECK_CLOSE_ABS(protoLayer.range(binX), 12., 1e-8);
CHECK_CLOSE_ABS(protoLayer.medium(binX), 0., 1e-8);
CHECK_CLOSE_ABS(protoLayer.min(binX), -6., 1e-8);
CHECK_CLOSE_ABS(protoLayer.max(binX), 6., 1e-8);
CHECK_CLOSE_ABS(protoLayer.range(binY), 6., 1e-8);
CHECK_CLOSE_ABS(protoLayer.medium(binY), 0., 1e-8);
CHECK_CLOSE_ABS(protoLayer.min(binY), -3., 1e-8);
CHECK_CLOSE_ABS(protoLayer.max(binY), 3., 1e-8);
CHECK_CLOSE_ABS(protoLayer.range(binZ), 12., 1e-8);
CHECK_CLOSE_ABS(protoLayer.medium(binZ), 0., 1e-8);
CHECK_CLOSE_ABS(protoLayer.min(binZ), -6., 1e-8);
CHECK_CLOSE_ABS(protoLayer.max(binZ), 6., 1e-8);
CHECK_CLOSE_ABS(protoLayer.max(binR), std::hypot(3, 6), 1e-8);
CHECK_CLOSE_ABS(protoLayer.min(binR), 3., 1e-8);

// Test 1a

Expand All @@ -127,16 +130,15 @@ BOOST_AUTO_TEST_CASE(ProtoLayerTests) {
auto protoLayerRot = createProtoLayer(AngleAxis3(-0.345, Vector3::UnitZ()) *
Transform3::Identity());

BOOST_CHECK_NE(protoLayer.min(BinningValue::binX), -6.);
CHECK_CLOSE_ABS(protoLayerRot.medium(BinningValue::binX), 0., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.medium(BinningValue::binY), 0., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.range(BinningValue::binZ), 12., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.medium(BinningValue::binZ), 0., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.min(BinningValue::binZ), -6., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.max(BinningValue::binZ), 6., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.min(BinningValue::binR), 3., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.max(BinningValue::binR), std::hypot(3, 6),
1e-8);
BOOST_CHECK_NE(protoLayer.min(binX), -6.);
CHECK_CLOSE_ABS(protoLayerRot.medium(binX), 0., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.medium(binY), 0., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.range(binZ), 12., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.medium(binZ), 0., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.min(binZ), -6., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.max(binZ), 6., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.min(binR), 3., 1e-8);
CHECK_CLOSE_ABS(protoLayerRot.max(binR), std::hypot(3, 6), 1e-8);

std::stringstream sstream;
protoLayerRot.toStream(sstream);
Expand All @@ -155,6 +157,111 @@ Extent in space :
BOOST_CHECK_EQUAL(sstream.str(), oString);
}

BOOST_AUTO_TEST_CASE(OrientedLayer) {
using enum BinningValue;
using namespace Acts::UnitLiterals;

Transform3 base = Transform3::Identity();

auto recBounds = std::make_shared<RectangleBounds>(3_mm, 6_mm);

std::vector<std::unique_ptr<DetectorElementBase>> detectorElements;

auto makeFan = [&](double yrot, double thickness = 0) {
detectorElements.clear();

std::size_t nSensors = 8;
double deltaPhi = 2 * M_PI / nSensors;
double r = 20_mm;
std::vector<std::shared_ptr<const Surface>> surfaces;
for (std::size_t i = 0; i < nSensors; i++) {
// Create a fan of sensors

Transform3 trf = base * AngleAxis3{yrot, Vector3::UnitY()} *
AngleAxis3{deltaPhi * i, Vector3::UnitZ()} *
Translation3(Vector3::UnitX() * r);

auto& element = detectorElements.emplace_back(
std::make_unique<DetectorElementStub>(trf, recBounds, thickness));

surfaces.push_back(element->surface().getSharedPtr());
}
return surfaces;
};

std::vector<std::shared_ptr<const Surface>> surfaces = makeFan(0_degree);

ProtoLayer protoLayer(tgContext, surfaces);

BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
BOOST_CHECK_CLOSE(protoLayer.min(binX), -23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.max(binX), 23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.min(binY), -23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.max(binY), 23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.min(binZ), 0_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.max(binZ), 0_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.min(binR), 17_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.max(binR), 23.769728648_mm, 1e-8);

surfaces = makeFan(45_degree);

// Do NOT provide rotation matrix: sizing will be affected
protoLayer = {tgContext, surfaces};

BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
BOOST_CHECK_CLOSE(protoLayer.min(binX), -16.26345596_mm, 1e-4);
BOOST_CHECK_CLOSE(protoLayer.max(binX), 16.26345596_mm, 1e-4);
BOOST_CHECK_CLOSE(protoLayer.min(binY), -23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.max(binY), 23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.min(binZ), -16.26345596_mm, 1e-4);
BOOST_CHECK_CLOSE(protoLayer.max(binZ), 16.26345596_mm, 1e-4);

protoLayer = {tgContext, surfaces,
Transform3{AngleAxis3{45_degree, Vector3::UnitY()}}.inverse()};

BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
BOOST_CHECK_CLOSE(protoLayer.range(binX), 46_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.min(binX), -23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.max(binX), 23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.range(binY), 46_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.min(binY), -23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.max(binY), 23_mm, 1e-8);
CHECK_SMALL(protoLayer.range(binZ), 1e-14);
CHECK_SMALL(protoLayer.min(binZ), 1e-14);
CHECK_SMALL(protoLayer.max(binZ), 1e-14);

surfaces = makeFan(0_degree, 10_mm);

protoLayer = {tgContext, surfaces};

BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
BOOST_CHECK_CLOSE(protoLayer.range(binX), 46_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.min(binX), -23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.max(binX), 23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.range(binY), 46_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.min(binY), -23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.max(binY), 23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.range(binZ), 10_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.min(binZ), -5_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.max(binZ), 5_mm, 1e-8);

surfaces = makeFan(45_degree, 10_mm);

protoLayer = {tgContext, surfaces,
Transform3{AngleAxis3{45_degree, Vector3::UnitY()}}.inverse()};

BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
BOOST_CHECK_CLOSE(protoLayer.range(binX), 46_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.min(binX), -23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.max(binX), 23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.range(binY), 46_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.min(binY), -23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.max(binY), 23_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.range(binZ), 10_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.min(binZ), -5_mm, 1e-8);
BOOST_CHECK_CLOSE(protoLayer.max(binZ), 5_mm, 1e-8);
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace Acts::Test::Layers
Loading