Skip to content

Commit 42c3bc9

Browse files
committed
ITS3: alignment
Signed-off-by: Felix Schlepper <felix.schlepper@cern.ch>
1 parent 22759e0 commit 42c3bc9

File tree

15 files changed

+1774
-18
lines changed

15 files changed

+1774
-18
lines changed

Detectors/Upgrades/ITS3/alignment/CMakeLists.txt

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,42 @@
99
# granted to it by virtue of its status as an Intergovernmental Organization
1010
# or submit itself to any jurisdiction.
1111

12+
# add_compile_options(-O0 -g -fPIC -fno-omit-frame-pointer)
1213
o2_add_library(ITS3Align
14+
TARGETVARNAME targetName
1315
SOURCES src/MisalignmentParameters.cxx
1416
src/MisalignmentHits.cxx
1517
src/MisalignmentManager.cxx
1618
src/Deformations.cxx
19+
src/AlignmentHierarchy.cxx
20+
src/AlignmentSensors.cxx
21+
src/AlignmentParams.cxx
22+
src/AlignmentTypes.cxx
23+
src/AlignmentSpec.cxx
1724
PUBLIC_LINK_LIBRARIES O2::MathUtils
1825
O2::Steer
1926
O2::ITSBase
20-
O2::ITSMFTSimulation)
27+
O2::ITSMFTSimulation
28+
O2::Framework
29+
O2::GlobalTrackingWorkflowReaders
30+
O2::GlobalTrackingWorkflowHelpers
31+
O2::DataFormatsGlobalTracking
32+
O2::DetectorsVertexing
33+
GBL::GBL)
34+
if (OpenMP_CXX_FOUND)
35+
target_compile_definitions(${targetName} PRIVATE WITH_OPENMP)
36+
target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX)
37+
endif()
2138

2239
o2_target_root_dictionary(ITS3Align
2340
HEADERS include/ITS3Align/MisalignmentParameters.h
2441
include/ITS3Align/MisalignmentHits.h
25-
include/ITS3Align/MisalignmentHits.h
26-
include/ITS3Align/Deformations.h)
42+
include/ITS3Align/Deformations.h
43+
include/ITS3Align/AlignmentParams.h
44+
include/ITS3Align/AlignmentTypes.h)
45+
46+
47+
o2_add_executable(alignment-workflow
48+
SOURCES src/alignment-workflow.cxx
49+
COMPONENT_NAME its3
50+
PUBLIC_LINK_LIBRARIES O2::ITS3Align)
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
#ifndef O2_ITS3_ALIGNMENT_HIERARCHY_H
13+
#define O2_ITS3_ALIGNMENT_HIERARCHY_H
14+
15+
#include <memory>
16+
#include <compare>
17+
#include <type_traits>
18+
#include <map>
19+
#include <utility>
20+
#include <vector>
21+
#include <ostream>
22+
23+
#include <Eigen/Dense>
24+
25+
#include <TGeoMatrix.h>
26+
#include <TGeoPhysicalNode.h>
27+
28+
namespace o2::its3::align
29+
{
30+
using Matrix36 = Eigen::Matrix<double, 3, 6>;
31+
using Matrix66 = Eigen::Matrix<double, 6, 6>;
32+
33+
using RigidBodyDOFMask = uint8_t;
34+
template <typename... Args>
35+
constexpr RigidBodyDOFMask DOF_BIT(Args... bits)
36+
{
37+
return (RigidBodyDOFMask{0} | ... | (RigidBodyDOFMask{1} << bits));
38+
}
39+
// DOFs are defined in LOC
40+
enum RigidBodyDOF : RigidBodyDOFMask {
41+
TX = 0, // Translation along local X
42+
TY, // Translation along local Y
43+
TZ, // Translation along local Z
44+
RX, // Rotation around local X
45+
RY, // Rotation around local Y
46+
RZ, // Rotation around local Z
47+
NDOF,
48+
};
49+
constexpr RigidBodyDOFMask RigidBodyDOFTra = DOF_BIT(TX, TY, TZ);
50+
constexpr RigidBodyDOFMask RigidBodyDOFRot = DOF_BIT(RX, RY, RZ);
51+
constexpr RigidBodyDOFMask RigidBodyDOFAll = RigidBodyDOFTra | RigidBodyDOFRot;
52+
constexpr RigidBodyDOFMask RigidBodyDOFNone = 0;
53+
constexpr RigidBodyDOFMask RigidBodyDOFPseudo = std::numeric_limits<RigidBodyDOFMask>::max(); // special value representing that the volume itself does not have any dofs but should not curtail the parent's ones
54+
static constexpr const char* RigidBodyDOFNames[RigidBodyDOF::NDOF] = {"TX", "TY", "TZ", "RX", "RY", "RZ"};
55+
inline bool hasRigidBodyDOF(RigidBodyDOFMask m, RigidBodyDOFMask d)
56+
{
57+
return (m == RigidBodyDOFPseudo) || (m & DOF_BIT(d));
58+
}
59+
inline void enableRigidBodyDOF(RigidBodyDOFMask& m, RigidBodyDOFMask d)
60+
{
61+
m |= DOF_BIT(d);
62+
}
63+
inline void disableRigidBodyDOF(RigidBodyDOFMask& m, RigidBodyDOFMask d)
64+
{
65+
m &= ~DOF_BIT(d);
66+
}
67+
// return the rigid body derivatives
68+
// trk has be at in the measurment frame
69+
auto getRigidBodyDerivatives(const auto& trk)
70+
{
71+
// calculate slopes
72+
const double tgl = trk.getTgl(), snp = trk.getSnp();
73+
const double csp = 1. / sqrt(1. + (tgl * tgl));
74+
const double u = trk.getY(), v = trk.getZ();
75+
const double uP = snp * csp, vP = tgl * csp;
76+
Matrix36 der;
77+
der.setZero();
78+
// columns: Tt, Tu, Tv, Rt, Ru, Rv
79+
// (X) (Y) (Z) (RX) (RY) (RZ)
80+
der << uP, -1., 0., v, v * uP, -u * uP,
81+
vP, 0., -1., -u, v * vP, -u * vP;
82+
return der;
83+
}
84+
85+
class GlobalLabel
86+
{
87+
// Millepede label is any positive integer [1....)
88+
public:
89+
using T = uint32_t;
90+
static constexpr int DOF_BITS = 5; // 0...4
91+
static constexpr int ID_BITS = 23; // 5...27
92+
static constexpr int SENS_BITS = 1; // 28
93+
static constexpr int TOTAL_BITS = sizeof(T) * 8;
94+
static constexpr int DET_BITS = TOTAL_BITS - (DOF_BITS + ID_BITS + SENS_BITS) - 1; // one less bit since GBL uses int!
95+
static constexpr T bitMask(int b) noexcept
96+
{
97+
return (T(1) << b) - T(1);
98+
}
99+
static constexpr int DOF_SHIFT = 0;
100+
static constexpr T DOF_MAX = (T(1) << DOF_BITS) - T(1);
101+
static constexpr T DOF_MASK = DOF_MAX << DOF_SHIFT;
102+
static constexpr int ID_SHIFT = DOF_BITS;
103+
static constexpr T ID_MAX = (T(1) << ID_BITS) - T(1);
104+
static constexpr T ID_MASK = ID_MAX << ID_SHIFT;
105+
static constexpr int SENS_SHIFT = ID_BITS + DOF_BITS;
106+
static constexpr T SENS_MAX = (T(1) << SENS_BITS) - T(1);
107+
static constexpr T SENS_MASK = SENS_MAX << SENS_SHIFT;
108+
static constexpr int DET_SHIFT = DOF_BITS + ID_BITS + SENS_BITS;
109+
static constexpr T DET_MAX = (T(1) << DET_BITS) - T(1);
110+
static constexpr T DET_MASK = DET_MAX << DET_SHIFT;
111+
112+
GlobalLabel(T det, T id, bool sens) : mID(((((id + 1) & ID_MAX) << ID_SHIFT) | ((det & DET_MAX) << DET_SHIFT) | ((sens & SENS_MAX) << SENS_SHIFT)))
113+
{
114+
}
115+
116+
constexpr T raw(T dof) const noexcept { return (mID & ~DOF_MASK) | ((dof & DOF_MAX) << DOF_SHIFT); }
117+
constexpr int rawGBL(T dof) const noexcept { return static_cast<int>(raw(dof)); }
118+
constexpr T id() const noexcept
119+
{
120+
return ((mID - 1) & ID_MASK) >> ID_SHIFT;
121+
}
122+
constexpr T det() const noexcept
123+
{
124+
return (mID & DET_MASK) >> DET_SHIFT;
125+
}
126+
constexpr bool sens() const noexcept
127+
{
128+
return (mID & SENS_MASK) >> SENS_SHIFT;
129+
}
130+
131+
std::string asString() const
132+
{
133+
return std::format("Det:{} Id:{} Sens:{}", det(), id(), sens());
134+
}
135+
136+
constexpr auto operator<=>(const GlobalLabel&) const noexcept = default;
137+
138+
private:
139+
T mID{0};
140+
};
141+
142+
// Rigid body constraints for the parents
143+
class HierarchyConstraint
144+
{
145+
public:
146+
HierarchyConstraint(std::string name, double value) : mName(std::move(name)), mValue(value) {}
147+
void add(uint32_t lab, double coeff)
148+
{
149+
mLabels.push_back(lab);
150+
mCoeff.push_back(coeff);
151+
}
152+
void write(std::ostream& os) const;
153+
auto getSize() const noexcept { return mLabels.size(); }
154+
155+
private:
156+
std::string mName; // name of the constraint
157+
double mValue{0.0}; // constraint value
158+
std::vector<uint32_t> mLabels; // parameter labels
159+
std::vector<double> mCoeff; // their coefficients
160+
};
161+
162+
class AlignableVolume
163+
{
164+
public:
165+
using Ptr = std::unique_ptr<AlignableVolume>;
166+
using SensorMapping = std::map<GlobalLabel, AlignableVolume*>;
167+
168+
AlignableVolume(const AlignableVolume&) = default;
169+
AlignableVolume(AlignableVolume&&) = delete;
170+
AlignableVolume& operator=(const AlignableVolume&) = default;
171+
AlignableVolume& operator=(AlignableVolume&&) = delete;
172+
AlignableVolume(const char* symName, uint32_t label, uint32_t det, bool sens, RigidBodyDOFMask dof);
173+
AlignableVolume(const char* symName, GlobalLabel label, RigidBodyDOFMask dof);
174+
virtual ~AlignableVolume() = default;
175+
176+
void finalise(uint8_t level = 0);
177+
178+
// steering file output
179+
void writeRigidBodyConstraints(std::ostream& os) const;
180+
void writeParameters(std::ostream& os) const;
181+
void writeTree(std::ostream& os, int indent = 0) const;
182+
183+
// tree-like
184+
auto getLevel() const noexcept { return mLevel; }
185+
bool isRoot() const noexcept { return mParent == nullptr; }
186+
bool isLeaf() const noexcept { return mChildren.empty(); }
187+
template <class T = AlignableVolume>
188+
requires std::derived_from<T, AlignableVolume>
189+
AlignableVolume* addChild(const char* symName, uint32_t label, uint32_t det, bool sens, RigidBodyDOFMask dof)
190+
{
191+
auto c = std::make_unique<T>(symName, label, det, sens, dof);
192+
return setParent(std::move(c));
193+
}
194+
template <class T = AlignableVolume>
195+
requires std::derived_from<T, AlignableVolume>
196+
AlignableVolume* addChild(const char* symName, GlobalLabel lbl, RigidBodyDOFMask dof)
197+
{
198+
auto c = std::make_unique<T>(symName, lbl, dof);
199+
return setParent(std::move(c));
200+
}
201+
202+
// bfs traversal
203+
void traverse(const std::function<void(AlignableVolume*)>& visitor)
204+
{
205+
visitor(this);
206+
for (auto& c : mChildren) {
207+
c->traverse(visitor);
208+
}
209+
}
210+
211+
std::string getSymName() const noexcept { return mSymName; }
212+
GlobalLabel getLabel() const noexcept { return mLabel; }
213+
AlignableVolume* getParent() const { return mParent; }
214+
size_t getNChildren() const noexcept { return mChildren.size(); }
215+
void setRigidBodyDOF(RigidBodyDOFMask m) noexcept { mDOF = m; }
216+
RigidBodyDOFMask getRigidBodyDOF() const noexcept { return mDOF; }
217+
218+
// transformation matrices
219+
virtual void defineMatrixL2G() {}
220+
virtual void defineMatrixT2L() {}
221+
virtual void computeJacobianL2T(const double* pos, Matrix66& jac) const {};
222+
const TGeoHMatrix& getL2P() const { return mL2P; }
223+
const TGeoHMatrix& getT2L() const { return mT2L; }
224+
const Matrix66& getJL2P() const { return mJL2P; }
225+
const Matrix66& getJP2L() const { return mJP2L; }
226+
227+
protected:
228+
/// matrices
229+
AlignableVolume* mParent{nullptr}; // parent
230+
TGeoPNEntry* mPNE{nullptr}; // physical entry
231+
TGeoPhysicalNode* mPN{nullptr}; // physical node
232+
TGeoHMatrix mL2G; // (LOC) -> (GLO)
233+
TGeoHMatrix mL2P; // (LOC) -> (PAR)
234+
Matrix66 mJL2P; // jac (LOC) -> (PAR)
235+
Matrix66 mJP2L; // jac (PAR) -> (LOC)
236+
TGeoHMatrix mT2L; // (TRK) -> (LOC)
237+
238+
private:
239+
double mPreSigma{0.0}; // asigned pre-sigma
240+
std::string mSymName; // unique symbolic name
241+
GlobalLabel mLabel; // internal global idetenifier
242+
uint8_t mLevel{0}; // depth-in tree
243+
RigidBodyDOFMask mDOF{RigidBodyDOFAll}; // allowed dofs
244+
245+
AlignableVolume* setParent(Ptr c)
246+
{
247+
c->mParent = this;
248+
mChildren.push_back(std::move(c));
249+
return mChildren.back().get();
250+
}
251+
std::vector<Ptr> mChildren; // children
252+
253+
void init();
254+
};
255+
256+
} // namespace o2::its3::align
257+
258+
#endif
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
#ifndef ALICEO2_ITS3_ALIGNMENTPARAMS_H_
12+
#define ALICEO2_ITS3_ALIGNMENTPARAMS_H_
13+
14+
#include "CommonUtils/ConfigurableParam.h"
15+
#include "CommonUtils/ConfigurableParamHelper.h"
16+
#include "DetectorsBase/Propagator.h"
17+
18+
namespace o2::its3::align
19+
{
20+
struct AlignmentParams : public o2::conf::ConfigurableParamHelper<AlignmentParams> {
21+
// Track selection
22+
float minPt = 1.f; // minimum pt required
23+
int minITSCls = 7; // minimum number of ITS clusters
24+
float maxITSChi2Ndf = 1.2; // maximum ITS track chi2
25+
26+
// propagation opt
27+
double maxSnp = 0.85;
28+
double maxStep = 2.0;
29+
// o2::base::PropagatorD::MatCorrType matCorrType = o2::base::PropagatorD::MatCorrType::USEMatCorrTGeo;
30+
o2::base::PropagatorD::MatCorrType matCorrType = o2::base::PropagatorD::MatCorrType::USEMatCorrLUT;
31+
32+
bool useStableRefit = true; // use input tracks as linearization point
33+
float minMS = 1e-6f; // minimum scattering to account for
34+
float maxChi2Ndf = 10; // maximum Chi2/Ndf allowed for GBL fit
35+
36+
// Ridder options
37+
int ridderMaxExtrap = 10;
38+
double ridderRelIniStep[5] = {0.01, 0.01, 0.02, 0.02, 0.02};
39+
double ridderMaxIniStep[5] = {0.1, 0.1, 0.05, 0.05, 0.05};
40+
double ridderShrinkFac = 2.0;
41+
double ridderEps = 1e-16;
42+
double ridderMaxJacDiagTol = 0.1; // max tolerance of diagonal elements away from 1
43+
44+
// MillePede output
45+
std::string milleBinFile = "mp2data.bin";
46+
std::string milleConFile = "mp2con.txt";
47+
std::string milleParamFile = "mp2param.txt";
48+
std::string milleTreeFile = "mp2tree.txt";
49+
50+
O2ParamDef(AlignmentParams, "ITS3AlignmentParams");
51+
};
52+
} // namespace o2::its3::align
53+
54+
#endif

0 commit comments

Comments
 (0)