Skip to content

Commit 9ddf142

Browse files
committed
ITS3: alignment account for tangential movement
Signed-off-by: Felix Schlepper <felix.schlepper@cern.ch>
1 parent 8cc7f07 commit 9ddf142

5 files changed

Lines changed: 62 additions & 1 deletion

File tree

Detectors/Upgrades/ITS3/alignment/include/ITS3Align/AlignmentMath.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct TrackSlopes {
2323
double dzdx{0.};
2424
};
2525

26+
double getSensorPhiWidth(int sensorID, double radius);
2627
std::pair<double, double> computeUV(double gloX, double gloY, double gloZ, int sensorID, double radius);
2728
TrackSlopes computeTrackSlopes(double snp, double tgl);
2829
std::vector<double> legendrePols(int order, double x);

Detectors/Upgrades/ITS3/alignment/src/AlignmentDOF.cxx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111

1212
#include "ITS3Align/AlignmentDOF.h"
1313

14+
#include <array>
1415
#include <cmath>
1516
#include <stdexcept>
1617

1718
#include "ITS3Align/AlignmentMath.h"
1819
#include "ITS3Base/SpecsV2.h"
20+
#include "CommonConstants/MathConstants.h"
1921

2022
namespace
2123
{
@@ -64,12 +66,34 @@ void LegendreDOFSet::fillDerivatives(const DerivativeContext& ctx, Eigen::Ref<Ei
6466
const auto [u, v] = o2::its3::align::computeUV(gloX, gloY, ctx.measZ, ctx.sensorID, o2::its3::constants::radii[ctx.layerID]);
6567
const auto pu = o2::its3::align::legendrePols(mOrder, u);
6668
const auto pv = o2::its3::align::legendrePols(mOrder, v);
69+
const double phiWidth = o2::its3::align::getSensorPhiWidth(ctx.sensorID, o2::its3::constants::radii[ctx.layerID]);
70+
71+
// same intergration as `evaluateLegendreShift' but now for each order separateley
72+
Eigen::VectorXd arcMismatch = Eigen::VectorXd::Zero(nDOFs());
73+
if (std::abs(u) > o2::constants::math::Almost0) {
74+
constexpr std::array<double, 8> x = {-0.9602898564975363, -0.7966664774136267, -0.5255324099163290, -0.1834346424956498, 0.1834346424956498, 0.5255324099163290, 0.7966664774136267, 0.9602898564975363};
75+
constexpr std::array<double, 8> w = {0.1012285362903763, 0.2223810344533745, 0.3137066458778873, 0.3626837833783620, 0.3626837833783620, 0.3137066458778873, 0.2223810344533745, 0.1012285362903763};
76+
const double mid = 0.5 * u;
77+
const double half = 0.5 * u;
78+
for (int iq = 0; iq < 8; ++iq) {
79+
const double up = mid + (half * x[iq]);
80+
const auto puQ = o2::its3::align::legendrePols(mOrder, up);
81+
int idx = 0;
82+
for (int i = 0; i <= mOrder; ++i) {
83+
for (int j = 0; j <= i; ++j) {
84+
arcMismatch[idx] += w[iq] * puQ[j] * pv[i - j];
85+
++idx;
86+
}
87+
}
88+
}
89+
arcMismatch *= 0.5 * phiWidth * half;
90+
}
6791

6892
int idx = 0;
6993
for (int i = 0; i <= mOrder; ++i) {
7094
for (int j = 0; j <= i; ++j) {
7195
const double basis = pu[j] * pv[i - j];
72-
out(0, idx) = ctx.dydx * basis;
96+
out(0, idx) = (ctx.dydx * basis) + arcMismatch[idx];
7397
out(1, idx) = ctx.dzdx * basis;
7498
++idx;
7599
}

Detectors/Upgrades/ITS3/alignment/src/AlignmentMath.cxx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@
2121
namespace o2::its3::align
2222
{
2323

24+
double getSensorPhiWidth(int sensorID, double radius)
25+
{
26+
const bool isTop = sensorID % 2 == 0;
27+
const double phiBorder1 = o2::math_utils::to02Pid(((isTop ? 0. : 1.) * TMath::Pi()) + std::asin(constants::equatorialGap / 2. / radius));
28+
const double phiBorder2 = o2::math_utils::to02Pid(((isTop ? 1. : 2.) * TMath::Pi()) - std::asin(constants::equatorialGap / 2. / radius));
29+
const double width = phiBorder2 - phiBorder1;
30+
return (width < 0.) ? width + TMath::TwoPi() : width;
31+
}
32+
2433
std::pair<double, double> computeUV(double gloX, double gloY, double gloZ, int sensorID, double radius)
2534
{
2635
const bool isTop = sensorID % 2 == 0;

Detectors/Upgrades/ITS3/alignment/src/AlignmentSpec.cxx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ void AlignmentSpec::process()
206206
buildT2V();
207207
}
208208

209+
if (mNThreads > 1 && !(mParams->misAlgJson.empty())) {
210+
LOGP(warn, "Applying misalignment works only single-threaded, forcing to 1");
211+
mNThreads = 1;
212+
}
209213
LOGP(info, "Starting fits with {} threads", mNThreads);
210214

211215
// Data
@@ -831,6 +835,9 @@ bool AlignmentSpec::applyMisalignment(Eigen::Vector2d& res, const FrameInfoExt&
831835
const auto prop = o2::base::PropagatorD::Instance();
832836

833837
const auto lbl = mRecoData->getITSTracksMCLabels()[iTrk];
838+
if (lbl.isFake()) {
839+
return false;
840+
}
834841
const auto mcTrk = mcReader->getTrack(lbl);
835842
if (!mcTrk) {
836843
return false;

Detectors/Upgrades/ITS3/alignment/src/MisalignmentUtils.cxx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
#include <cmath>
1616
#include <fstream>
1717
#include <vector>
18+
#include <array>
1819

1920
#include <TMatrixD.h>
2021
#include <nlohmann/json.hpp>
2122

2223
#include "Framework/Logger.h"
24+
#include "CommonConstants/MathConstants.h"
2325
#include "ITS3Base/SpecsV2.h"
2426

2527
namespace o2::its3::align
@@ -98,9 +100,27 @@ MisalignmentShift evaluateLegendreShift(const SensorMisalignment& sensor, const
98100
auto [u, v] = computeUV(gloX, gloY, gloZ, frame.sensorID, constants::radii[frame.layerID]);
99101
const double h = sensor.legendre(u, v);
100102

103+
// this is the shift due to back-projection of the track on the ideal surface
101104
shift.dy = slopes.dydx * h;
102105
shift.dz = slopes.dzdx * h;
103106

107+
if (std::abs(u) > o2::constants::math::Almost0) {
108+
// account for additional tangential movement due to radial shift
109+
// we have to approximate the difference in arc-length from the reference pnt on the deformed surface
110+
// this is done by integrating the height function via Gauss-Legendre quadrature (from Numerical recipes 4.6 [1])
111+
constexpr std::array<double, 8> x = {-0.9602898564975363, -0.7966664774136267, -0.5255324099163290, -0.1834346424956498, 0.1834346424956498, 0.5255324099163290, 0.7966664774136267, 0.9602898564975363};
112+
constexpr std::array<double, 8> w = {0.1012285362903763, 0.2223810344533745, 0.3137066458778873, 0.3626837833783620, 0.3626837833783620, 0.3137066458778873, 0.2223810344533745, 0.1012285362903763};
113+
const double mid = 0.5 * u;
114+
const double half = 0.5 * u;
115+
double integral = 0.;
116+
for (int i = 0; i < 8; ++i) {
117+
const double up = mid + (half * x[i]);
118+
integral += w[i] * sensor.legendre(up, v);
119+
}
120+
integral *= half;
121+
shift.dy += 0.5 * getSensorPhiWidth(frame.sensorID, constants::radii[frame.layerID]) * integral;
122+
}
123+
104124
const double newGloY = gloY + (shift.dy * std::cos(frame.alpha));
105125
const double newGloX = gloX - (shift.dy * std::sin(frame.alpha));
106126
const double newGloZ = gloZ + shift.dz;

0 commit comments

Comments
 (0)