21#include <nlohmann/json.hpp>
32 return std::all_of(
sensors.begin(),
sensors.end(), [](
const auto& sensor) { return sensor.empty(); });
38 if (jsonPath.empty()) {
42 std::ifstream
f(jsonPath);
44 LOGP(fatal,
"Cannot open misalignment JSON file: {}", jsonPath);
47 using json = nlohmann::json;
48 const auto data = json::parse(
f);
49 for (
const auto& item :
data) {
50 const int id = item[
"id"].get<
int>();
55 auto& sensor = model[
id];
56 if (item.contains(
"matrix")) {
57 auto v = item[
"matrix"].get<std::vector<std::vector<double>>>();
59 LOGP(fatal,
"Legendre matrix for sensor {} is empty in {}",
id, jsonPath);
61 TMatrixD
m(
v.size(),
v.back().size());
62 for (std::size_t
r{0};
r <
v.size(); ++
r) {
63 for (std::size_t
c{0};
c <
v[
r].size(); ++
c) {
68 sensor.hasLegendre =
true;
70 if (item.contains(
"inextensional")) {
71 const auto& inex = item[
"inextensional"];
72 sensor.hasInextensional =
true;
73 if (inex.contains(
"modes")) {
74 for (
const auto& [
key,
val] : inex[
"modes"].items()) {
75 sensor.inextensional.modes[std::stoi(
key)] =
val.get<std::array<double, 4>>();
78 if (inex.contains(
"alpha")) {
79 sensor.inextensional.alpha = inex[
"alpha"].get<
double>();
81 if (inex.contains(
"beta")) {
82 sensor.inextensional.beta = inex[
"beta"].get<
double>();
97 const double gloX = frame.
x * std::cos(frame.
alpha);
98 const double gloY = frame.
x * std::sin(frame.
alpha);
99 const double gloZ = frame.
z;
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]);
124 const double newGloY = gloY + (shift.
dy * std::cos(frame.
alpha));
125 const double newGloX = gloX - (shift.
dy * std::sin(frame.
alpha));
126 const double newGloZ = gloZ + shift.
dz;
128 shift.
accepted = std::abs(uNew) <= 1. && std::abs(vNew) <= 1.;
140 const double phi = std::atan2(
r * std::sin(frame.
alpha),
r * std::cos(frame.
alpha));
141 const double z = frame.
z;
144 double uz = 0., uphi = 0., ur = 0.;
145 for (
const auto& [
n,
coeffs] : inex.modes) {
147 const double sn = std::sin(
n * phi);
148 const double cn = std::cos(
n * phi);
149 const int n2 =
n *
n;
151 const double fn = (a_n * cn) + (b_n * sn);
152 const double fpn = (-
n * a_n * sn) + (
n * b_n * cn);
153 const double fppn = (-n2 * a_n * cn) - (n2 * b_n * sn);
154 const double gn = (c_n * cn) + (d_n * sn);
155 const double gpn = (-
n * c_n * sn) + (
n * d_n * cn);
158 uphi += -(
z /
r) * fpn + gn;
159 ur += (
z /
r) * fppn - gpn;
162 uz += inex.alpha * phi;
163 uphi += -(
z /
r) * inex.alpha + inex.beta * phi;
166 shift.
dy = -uphi + (slopes.
dydx * ur);
167 shift.
dz = -uz + (slopes.
dzdx * ur);
Class for time synchronization of RawReader instances.
GLint GLenum GLint const GLfloat * coeffs
GLubyte GLubyte GLubyte GLubyte w
GLdouble GLdouble GLdouble z
MisalignmentShift evaluateInextensionalShift(const SensorMisalignment &sensor, const MisalignmentFrame &frame, const TrackSlopes &slopes)
MisalignmentModel loadMisalignmentModel(const std::string &jsonPath)
double getSensorPhiWidth(int sensorID, double radius)
MisalignmentShift evaluateLegendreShift(const SensorMisalignment &sensor, const MisalignmentFrame &frame, const TrackSlopes &slopes)
std::pair< double, double > computeUV(double gloX, double gloY, double gloZ, int sensorID, double radius)
constexpr std::array< double, nLayers > radii
bool empty() const noexcept
static constexpr std::size_t NSensors
std::array< SensorMisalignment, NSensors > sensors
o2::math_utils::Legendre2DPolynominal legendre
InextensionalMisalignment inextensional