forked from sPHENIX-Collaboration/acts
/
AlignmentContextTests.cpp
201 lines (164 loc) · 7.08 KB
/
AlignmentContextTests.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// This file is part of the Acts project.
//
// Copyright (C) 2017-2019 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 <boost/test/unit_test.hpp>
#include <array>
#include <memory>
#include "Acts/Geometry/DetectorElementBase.hpp"
#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Surfaces/PlanarBounds.hpp"
#include "Acts/Surfaces/PlaneSurface.hpp"
#include "Acts/Surfaces/RectangleBounds.hpp"
#include "Acts/Utilities/Definitions.hpp"
#include "Acts/Utilities/Units.hpp"
using namespace Acts::UnitLiterals;
namespace Acts {
namespace Test {
/// @class AlignmentContext
struct AlignmentContext {
/// We have 2 different transforms
std::shared_ptr<const std::array<Transform3D, 2>> alignmentStore = nullptr;
/// Context index
unsigned int alignmentIndex{0};
/// Default contructor
AlignmentContext() {}
/// Constructor with Store and context index
AlignmentContext(std::shared_ptr<const std::array<Transform3D, 2>> aStore,
unsigned int aIndex = 0)
: alignmentStore(std::move(aStore)), alignmentIndex(aIndex) {}
};
/// @class AlignableDetectorElement
///
/// This is a lightweight type of detector element,
/// it simply implements the base class.
class AlignableDetectorElement : public DetectorElementBase {
public:
// Deleted default constructor
AlignableDetectorElement() = delete;
/// Constructor for single sided detector element
/// - bound to a Plane Surface
///
/// @param transform is the transform that element the layer in 3D frame
/// @param pBounds is the planar bounds for the planar detector element
/// @param thickness is the module thickness
AlignableDetectorElement(std::shared_ptr<const Transform3D> transform,
std::shared_ptr<const PlanarBounds> pBounds,
double thickness)
: DetectorElementBase(),
m_elementTransform(std::move(transform)),
m_elementThickness(thickness) {
auto mutableSurface = Surface::makeShared<PlaneSurface>(pBounds, *this);
m_elementSurface = mutableSurface;
}
/// Destructor
~AlignableDetectorElement() override { /*nop */
}
/// Return local to global transform associated with this identifier
///
/// @param gctx The current geometry context object, e.g. alignment
///
/// @note this is called from the surface().transform() in the PROXY mode
const Transform3D& transform(const GeometryContext& gctx) const override;
/// Return surface associated with this detector element
const Surface& surface() const override;
/// The maximal thickness of the detector element wrt normal axis
double thickness() const override;
private:
/// the transform for positioning in 3D space
std::shared_ptr<const Transform3D> m_elementTransform;
/// the surface represented by it
std::shared_ptr<const Surface> m_elementSurface{nullptr};
/// the element thickness
double m_elementThickness{0.};
};
inline const Transform3D& AlignableDetectorElement::transform(
const GeometryContext& gctx) const {
auto alignContext = std::any_cast<AlignmentContext>(gctx);
if (alignContext.alignmentStore != nullptr and
alignContext.alignmentIndex < 2) {
return (*(alignContext.alignmentStore))[alignContext.alignmentIndex];
}
return (*m_elementTransform);
}
inline const Surface& AlignableDetectorElement::surface() const {
return *m_elementSurface;
}
inline double AlignableDetectorElement::thickness() const {
return m_elementThickness;
}
/// Unit test for creating compliant/non-compliant Surface object
BOOST_AUTO_TEST_CASE(AlignmentContextTests) {
// The nominal and alingments
Vector3D nominalCenter(0., 0., 0.);
Vector3D negativeCenter(0., 0., -1.);
Vector3D positiveCenter(0., 0., 1.);
// Checkpoints
Vector3D onNominal(3., 3., 0.);
Vector3D onNegative(3., 3., -1.);
Vector3D onPositive(3., 3., 1.);
// Local position
Vector2D localPosition(3., 3.);
// A position place holder and dymmy momentum
Vector3D globalPosition(100_cm, 100_cm, 100_cm);
Vector3D dummyMomentum(4., 4., 4.);
Transform3D negativeTransform = Transform3D::Identity();
negativeTransform.translation() = negativeCenter;
Transform3D positiveTransform = Transform3D::Identity();
positiveTransform.translation() = positiveCenter;
std::array<Transform3D, 2> alignmentArray = {negativeTransform,
positiveTransform};
std::shared_ptr<const std::array<Transform3D, 2>> alignmentStore =
std::make_shared<const std::array<Transform3D, 2>>(alignmentArray);
// The detector element at nominal position
AlignableDetectorElement alignedElement(
std::make_shared<const Transform3D>(Transform3D::Identity()),
std::make_shared<const RectangleBounds>(100_cm, 100_cm), 1_mm);
const auto& alignedSurface = alignedElement.surface();
// The alignment centexts
AlignmentContext defaultContext{};
AlignmentContext negativeContext(alignmentStore, 0);
AlignmentContext positiveContext(alignmentStore, 1);
// Test the transforms
BOOST_CHECK(alignedSurface.transform(defaultContext)
.isApprox(Transform3D::Identity()));
BOOST_CHECK(
alignedSurface.transform(negativeContext).isApprox(negativeTransform));
BOOST_CHECK(
alignedSurface.transform(positiveContext).isApprox(positiveTransform));
// Test the centers
BOOST_CHECK_EQUAL(alignedSurface.center(defaultContext), nominalCenter);
BOOST_CHECK_EQUAL(alignedSurface.center(negativeContext), negativeCenter);
BOOST_CHECK_EQUAL(alignedSurface.center(positiveContext), positiveCenter);
// Test OnSurface
BOOST_CHECK(
alignedSurface.isOnSurface(defaultContext, onNominal, dummyMomentum));
BOOST_CHECK(
alignedSurface.isOnSurface(negativeContext, onNegative, dummyMomentum));
BOOST_CHECK(
alignedSurface.isOnSurface(positiveContext, onPositive, dummyMomentum));
// Test local to Global and vice versa
alignedSurface.localToGlobal(defaultContext, localPosition, dummyMomentum,
globalPosition);
BOOST_CHECK_EQUAL(globalPosition, onNominal);
alignedSurface.globalToLocal(defaultContext, onNominal, dummyMomentum,
localPosition);
BOOST_CHECK_EQUAL(localPosition, Vector2D(3., 3.));
alignedSurface.localToGlobal(negativeContext, localPosition, dummyMomentum,
globalPosition);
BOOST_CHECK_EQUAL(globalPosition, onNegative);
alignedSurface.globalToLocal(negativeContext, onNegative, dummyMomentum,
localPosition);
BOOST_CHECK_EQUAL(localPosition, Vector2D(3., 3.));
alignedSurface.localToGlobal(positiveContext, localPosition, dummyMomentum,
globalPosition);
BOOST_CHECK_EQUAL(globalPosition, onPositive);
alignedSurface.globalToLocal(positiveContext, onPositive, dummyMomentum,
localPosition);
BOOST_CHECK_EQUAL(localPosition, Vector2D(3., 3.));
}
} // namespace Test
} // namespace Acts