22#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;
74 if (inex.contains(
"f")) {
75 for (
const auto& [
key,
val] : inex[
"f"].items()) {
76 sensor.inextensional.f[std::stoi(
key)] =
val.get<
double>();
79 if (inex.contains(
"g")) {
80 for (
const auto& [
key,
val] : inex[
"g"].items()) {
81 sensor.inextensional.g[std::stoi(
key)] =
val.get<
double>();
84 if (inex.contains(
"h")) {
85 for (
const auto& [
key,
val] : inex[
"h"].items()) {
86 const auto sep =
key.find(
'_');
87 if (sep == std::string::npos) {
88 LOGP(fatal,
"Inextensional h key '{}' for sensor {} must be of the form '<k>_<l>' in {}",
key,
id, jsonPath);
90 const int k = std::stoi(
key.substr(0, sep));
91 const int l = std::stoi(
key.substr(sep + 1));
93 LOGP(fatal,
"Inextensional h key '{}' for sensor {}: l must be >= 1 (l = 0 is spanned by g) in {}",
key,
id, jsonPath);
95 sensor.inextensional.h[{k, l}] =
val.get<
double>();
102 const auto& parsed = sensor.inextensional;
103 if (parsed.f.empty() && parsed.g.empty() && parsed.h.empty()) {
105 "Sensor {}: 'inextensional' block in {} contains none of the expected "
106 "keys 'f', 'g', 'h' - no deformation would be applied. Keys present: {}",
107 id, jsonPath, [&inex] { std::string s;
for (
const auto& [k,
v] : inex.items()) { s += (s.empty() ?
"" :
", ") + k; }
return s; }());
122 const double gloX = frame.
x * std::cos(frame.
alpha);
123 const double gloY = frame.
x * std::sin(frame.
alpha);
124 const double gloZ = frame.
z;
132 const double newGloY = gloY + (shift.
dy * std::cos(frame.
alpha));
133 const double newGloX = gloX - (shift.
dy * std::sin(frame.
alpha));
134 const double newGloZ = gloZ + shift.
dz;
136 shift.
accepted = std::abs(uNew) <= 1. && std::abs(vNew) <= 1.;
148 const double gloX = frame.
x * std::cos(frame.
alpha);
149 const double gloY = frame.
x * std::sin(frame.
alpha);
152 const double zOverR = frame.
z /
r;
156 for (
const auto& [k,
val] : inex.f) {
157 maxK = std::max(maxK, k);
159 for (
const auto& [k,
val] : inex.g) {
160 maxK = std::max(maxK, k);
162 int maxKh = 0, maxL = 0;
163 for (
const auto& [kl,
val] : inex.h) {
164 maxKh = std::max(maxKh, kl.first);
165 maxL = std::max(maxL, kl.second);
173 double uz = 0., uphi = 0., ur = 0.;
174 for (
const auto& [k, fk] : inex.f) {
176 uphi += -zOverR * cPhi * fk * pu1[k];
177 ur += zOverR * cPhi * cPhi * fk * pu2[k];
179 for (
const auto& [k, gk] : inex.g) {
181 ur += -cPhi * gk * pu1[k];
183 if (!inex.h.empty()) {
185 for (
const auto& [kl, hkl] : inex.h) {
186 ur += hkl * pu[kl.first] * pv[kl.second];
190 shift.
dy = -uphi + (slopes.
dydx * ur);
191 shift.
dz = -uz + (slopes.
dzdx * ur);
Class for time synchronization of RawReader instances.
std::vector< double > legendrePolsD2(int order, double x)
MisalignmentShift evaluateInextensionalShift(const SensorMisalignment &sensor, const MisalignmentFrame &frame, const TrackSlopes &slopes)
MisalignmentModel loadMisalignmentModel(const std::string &jsonPath)
std::vector< double > legendrePolsD1(int order, double x)
MisalignmentShift evaluateLegendreShift(const SensorMisalignment &sensor, const MisalignmentFrame &frame, const TrackSlopes &slopes)
double phiScale(double radius)
std::vector< double > legendrePols(int order, double x)
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