Skip to content

Commit d28d1e5

Browse files
committed
ITS3: alignment
Signed-off-by: Felix Schlepper <felix.schlepper@cern.ch>
1 parent 4fe8ef8 commit d28d1e5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3208
-2141
lines changed

Detectors/Upgrades/ITS3/alignment/CMakeLists.txt

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,37 @@
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
13-
SOURCES src/MisalignmentParameters.cxx
14-
src/MisalignmentHits.cxx
15-
src/MisalignmentManager.cxx
16-
src/Deformations.cxx
14+
TARGETVARNAME targetName
15+
SOURCES src/AlignmentHierarchy.cxx
16+
src/AlignmentSensors.cxx
17+
src/AlignmentParams.cxx
18+
src/AlignmentTypes.cxx
19+
src/AlignmentSpec.cxx
1720
PUBLIC_LINK_LIBRARIES O2::MathUtils
1821
O2::Steer
1922
O2::ITSBase
20-
O2::ITSMFTSimulation)
23+
O2::ITSMFTSimulation
24+
O2::ITS3Reconstruction
25+
O2::Framework
26+
O2::GlobalTrackingWorkflowReaders
27+
O2::GlobalTrackingWorkflowHelpers
28+
O2::DataFormatsGlobalTracking
29+
O2::DetectorsVertexing
30+
nlohmann_json::nlohmann_json
31+
GBL::GBL)
32+
if (OpenMP_CXX_FOUND)
33+
target_compile_definitions(${targetName} PRIVATE WITH_OPENMP)
34+
target_link_libraries(${targetName} PRIVATE OpenMP::OpenMP_CXX)
35+
endif()
2136

2237
o2_target_root_dictionary(ITS3Align
23-
HEADERS include/ITS3Align/MisalignmentParameters.h
24-
include/ITS3Align/MisalignmentHits.h
25-
include/ITS3Align/MisalignmentHits.h
26-
include/ITS3Align/Deformations.h)
38+
HEADERS include/ITS3Align/AlignmentParams.h
39+
include/ITS3Align/AlignmentTypes.h)
40+
41+
42+
o2_add_executable(alignment-workflow
43+
SOURCES src/alignment-workflow.cxx
44+
COMPONENT_NAME its3
45+
PUBLIC_LINK_LIBRARIES O2::ITS3Align)
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
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+
// Layout: DOF(5) | CALIB(1) | ID(22) | SENS(1) | DET(2) = 31 usable bits (MSB reserved, GBL uses signed int)
89+
public:
90+
using T = uint32_t;
91+
static constexpr int DOF_BITS = 5; // bits 0-4
92+
static constexpr int CALIB_BITS = 1; // bit 5: 0 = rigid body, 1 = calibration
93+
static constexpr int ID_BITS = 22; // bits 6-27
94+
static constexpr int SENS_BITS = 1; // bit 28
95+
static constexpr int TOTAL_BITS = sizeof(T) * 8;
96+
static constexpr int DET_BITS = TOTAL_BITS - (DOF_BITS + CALIB_BITS + ID_BITS + SENS_BITS) - 1; // one less bit since GBL uses int!
97+
static constexpr T bitMask(int b) noexcept
98+
{
99+
return (T(1) << b) - T(1);
100+
}
101+
static constexpr int DOF_SHIFT = 0;
102+
static constexpr T DOF_MAX = (T(1) << DOF_BITS) - T(1);
103+
static constexpr T DOF_MASK = DOF_MAX << DOF_SHIFT;
104+
static constexpr int CALIB_SHIFT = DOF_BITS;
105+
static constexpr T CALIB_MAX = (T(1) << CALIB_BITS) - T(1);
106+
static constexpr T CALIB_MASK = CALIB_MAX << CALIB_SHIFT;
107+
static constexpr int ID_SHIFT = DOF_BITS + CALIB_BITS;
108+
static constexpr T ID_MAX = (T(1) << ID_BITS) - T(1);
109+
static constexpr T ID_MASK = ID_MAX << ID_SHIFT;
110+
static constexpr int SENS_SHIFT = DOF_BITS + CALIB_BITS + ID_BITS;
111+
static constexpr T SENS_MAX = (T(1) << SENS_BITS) - T(1);
112+
static constexpr T SENS_MASK = SENS_MAX << SENS_SHIFT;
113+
static constexpr int DET_SHIFT = DOF_BITS + CALIB_BITS + ID_BITS + SENS_BITS;
114+
static constexpr T DET_MAX = (T(1) << DET_BITS) - T(1);
115+
static constexpr T DET_MASK = DET_MAX << DET_SHIFT;
116+
117+
GlobalLabel(T det, T id, bool sens, bool calib = false)
118+
: mID((((id + 1) & ID_MAX) << ID_SHIFT) |
119+
((det & DET_MAX) << DET_SHIFT) |
120+
((T(sens) & SENS_MAX) << SENS_SHIFT) |
121+
((T(calib) & CALIB_MAX) << CALIB_SHIFT))
122+
{
123+
}
124+
125+
/// produce the raw Millepede label for a given DOF index (rigid body: calib=0 in label)
126+
constexpr T raw(T dof) const noexcept { return (mID & ~DOF_MASK) | ((dof & DOF_MAX) << DOF_SHIFT); }
127+
constexpr int rawGBL(T dof) const noexcept { return static_cast<int>(raw(dof)); }
128+
129+
/// return a copy of this label with the CALIB bit set (for calibration DOFs on same volume)
130+
GlobalLabel asCalib() const noexcept
131+
{
132+
GlobalLabel c{*this};
133+
c.mID |= (T(1) << CALIB_SHIFT);
134+
return c;
135+
}
136+
137+
constexpr T id() const noexcept { return ((mID >> ID_SHIFT) & ID_MAX) - 1; }
138+
constexpr T det() const noexcept { return (mID & DET_MASK) >> DET_SHIFT; }
139+
constexpr bool sens() const noexcept { return (mID & SENS_MASK) >> SENS_SHIFT; }
140+
constexpr bool calib() const noexcept { return (mID & CALIB_MASK) >> CALIB_SHIFT; }
141+
142+
std::string asString() const
143+
{
144+
return std::format("Det:{} Id:{} Sens:{} Calib:{}", det(), id(), sens(), calib());
145+
}
146+
147+
constexpr auto operator<=>(const GlobalLabel&) const noexcept = default;
148+
149+
private:
150+
T mID{0};
151+
};
152+
153+
// Rigid body constraints for the parents
154+
class HierarchyConstraint
155+
{
156+
public:
157+
HierarchyConstraint(std::string name, double value) : mName(std::move(name)), mValue(value) {}
158+
void add(uint32_t lab, double coeff)
159+
{
160+
mLabels.push_back(lab);
161+
mCoeff.push_back(coeff);
162+
}
163+
void write(std::ostream& os) const;
164+
auto getSize() const noexcept { return mLabels.size(); }
165+
166+
private:
167+
std::string mName; // name of the constraint
168+
double mValue{0.0}; // constraint value
169+
std::vector<uint32_t> mLabels; // parameter labels
170+
std::vector<double> mCoeff; // their coefficients
171+
};
172+
173+
class AlignableVolume
174+
{
175+
public:
176+
using Ptr = std::unique_ptr<AlignableVolume>;
177+
using SensorMapping = std::map<GlobalLabel, AlignableVolume*>;
178+
179+
AlignableVolume(const AlignableVolume&) = default;
180+
AlignableVolume(AlignableVolume&&) = delete;
181+
AlignableVolume& operator=(const AlignableVolume&) = default;
182+
AlignableVolume& operator=(AlignableVolume&&) = delete;
183+
AlignableVolume(const char* symName, uint32_t label, uint32_t det, bool sens, RigidBodyDOFMask dof);
184+
AlignableVolume(const char* symName, GlobalLabel label, RigidBodyDOFMask dof);
185+
virtual ~AlignableVolume() = default;
186+
187+
void finalise(uint8_t level = 0);
188+
189+
// steering file output
190+
void writeRigidBodyConstraints(std::ostream& os) const;
191+
void writeParameters(std::ostream& os) const;
192+
void writeTree(std::ostream& os, int indent = 0) const;
193+
194+
// tree-like
195+
auto getLevel() const noexcept { return mLevel; }
196+
bool isRoot() const noexcept { return mParent == nullptr; }
197+
bool isLeaf() const noexcept { return mChildren.empty(); }
198+
template <class T = AlignableVolume>
199+
requires std::derived_from<T, AlignableVolume>
200+
AlignableVolume* addChild(const char* symName, uint32_t label, uint32_t det, bool sens, RigidBodyDOFMask dof)
201+
{
202+
auto c = std::make_unique<T>(symName, label, det, sens, dof);
203+
return setParent(std::move(c));
204+
}
205+
template <class T = AlignableVolume>
206+
requires std::derived_from<T, AlignableVolume>
207+
AlignableVolume* addChild(const char* symName, GlobalLabel lbl, RigidBodyDOFMask dof)
208+
{
209+
auto c = std::make_unique<T>(symName, lbl, dof);
210+
return setParent(std::move(c));
211+
}
212+
213+
// bfs traversal
214+
void traverse(const std::function<void(AlignableVolume*)>& visitor)
215+
{
216+
visitor(this);
217+
for (auto& c : mChildren) {
218+
c->traverse(visitor);
219+
}
220+
}
221+
222+
std::string getSymName() const noexcept { return mSymName; }
223+
GlobalLabel getLabel() const noexcept { return mLabel; }
224+
AlignableVolume* getParent() const { return mParent; }
225+
size_t getNChildren() const noexcept { return mChildren.size(); }
226+
void setRigidBodyDOF(RigidBodyDOFMask m) noexcept { mDOF = m; }
227+
RigidBodyDOFMask getRigidBodyDOF() const noexcept { return mDOF; }
228+
229+
// calibration DOFs (e.g. Legendre deformation coefficients)
230+
void setNCalibDOFs(int n) noexcept { mNCalibDOFs = n; }
231+
int getNCalibDOFs() const noexcept { return mNCalibDOFs; }
232+
233+
// transformation matrices
234+
virtual void defineMatrixL2G() {}
235+
virtual void defineMatrixT2L() {}
236+
virtual void computeJacobianL2T(const double* pos, Matrix66& jac) const {};
237+
const TGeoHMatrix& getL2P() const { return mL2P; }
238+
const TGeoHMatrix& getT2L() const { return mT2L; }
239+
const Matrix66& getJL2P() const { return mJL2P; }
240+
const Matrix66& getJP2L() const { return mJP2L; }
241+
242+
protected:
243+
/// matrices
244+
AlignableVolume* mParent{nullptr}; // parent
245+
TGeoPNEntry* mPNE{nullptr}; // physical entry
246+
TGeoPhysicalNode* mPN{nullptr}; // physical node
247+
TGeoHMatrix mL2G; // (LOC) -> (GLO)
248+
TGeoHMatrix mL2P; // (LOC) -> (PAR)
249+
Matrix66 mJL2P; // jac (LOC) -> (PAR)
250+
Matrix66 mJP2L; // jac (PAR) -> (LOC)
251+
TGeoHMatrix mT2L; // (TRK) -> (LOC)
252+
253+
private:
254+
double mPreSigma{0.0}; // asigned pre-sigma
255+
std::string mSymName; // unique symbolic name
256+
GlobalLabel mLabel; // internal global idetenifier
257+
uint8_t mLevel{0}; // depth-in tree
258+
RigidBodyDOFMask mDOF{RigidBodyDOFAll}; // allowed dofs
259+
int mNCalibDOFs{0}; // number of calibration DOFs (0 = none)
260+
261+
AlignableVolume* setParent(Ptr c)
262+
{
263+
c->mParent = this;
264+
mChildren.push_back(std::move(c));
265+
return mChildren.back().get();
266+
}
267+
std::vector<Ptr> mChildren; // children
268+
269+
void init();
270+
};
271+
272+
} // namespace o2::its3::align
273+
274+
#endif
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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 corrType = o2::base::PropagatorD::MatCorrType::USEMatCorrLUT;
31+
32+
bool useStableRef = 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+
float extraClsErrY[7] = {0};
37+
float extraClsErrZ[7] = {0};
38+
39+
// misalignment simulation
40+
bool doMisalignment = false; // simulate Legendre deformation on ITS3 layers
41+
bool doMisalignmentRB = false; // simulate rigid body misalignment on ITS3 layers
42+
std::string misAlgJson; // JSON file with deformation and/or rigid body params
43+
44+
// Legendre DOFs for Millepede
45+
int legendreOrder = 3; // max Legendre order in phi (u) direction (0..N -> N+1 terms)
46+
47+
// Ridder options
48+
int ridderMaxExtrap = 10;
49+
double ridderRelIniStep[5] = {0.01, 0.01, 0.02, 0.02, 0.02};
50+
double ridderMaxIniStep[5] = {0.1, 0.1, 0.05, 0.05, 0.05};
51+
double ridderShrinkFac = 2.0;
52+
double ridderEps = 1e-16;
53+
54+
// MillePede output
55+
std::string milleBinFile = "mp2data.bin";
56+
std::string milleConFile = "mp2con.txt";
57+
std::string milleParamFile = "mp2param.txt";
58+
std::string milleTreeFile = "mp2tree.txt";
59+
60+
O2ParamDef(AlignmentParams, "ITS3AlignmentParams");
61+
};
62+
} // namespace o2::its3::align
63+
64+
#endif

0 commit comments

Comments
 (0)