Project
Loading...
Searching...
No Matches
AlignmentSensors.cxx
Go to the documentation of this file.
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#include <TGeoManager.h>
13#include <TGeoPhysicalNode.h>
14
15#include "Framework/Logger.h"
19
20namespace o2::its3::align
21{
22
24{
25 uint32_t gLbl{0}, det{0};
27 AlignableVolume *volHB{nullptr}, *volSt{nullptr}, *volHSt{nullptr}, *volMod{nullptr};
28 std::unordered_map<std::string, AlignableVolume*> sym2vol;
29
30 auto root = std::make_unique<AlignableVolume>(geom->composeSymNameITS(), gLbl++, det, false);
31 sym2vol[root->getSymName()] = root.get();
32 for (int ilr = 0; ilr < geom->getNumberOfLayers(); ilr++) {
33 for (int ihb = 0; ihb < geom->getNumberOfHalfBarrels(); ihb++) {
34 volHB = root->addChild(geom->composeSymNameHalfBarrel(ilr, ihb), gLbl++, det, false);
35 sym2vol[volHB->getSymName()] = volHB;
36 int nstavesHB = geom->getNumberOfStaves(ilr) / 2;
37 for (int ist = 0; ist < nstavesHB; ist++) {
38 volSt = volHB->addChild(geom->composeSymNameStave(ilr, ihb, ist), gLbl++, det, false);
39 sym2vol[volSt->getSymName()] = volSt;
40 for (int ihst = 0; ihst < geom->getNumberOfHalfStaves(ilr); ihst++) {
41 volHSt = volSt->addChild(geom->composeSymNameHalfStave(ilr, ihb, ist, ihst), gLbl++, det, false);
42 sym2vol[volHSt->getSymName()] = volHSt;
43 for (int imd = 0; imd < geom->getNumberOfModules(ilr); imd++) {
44 volMod = volHSt->addChild(geom->composeSymNameModule(ilr, ihb, ist, ihst, imd), gLbl++, det, false);
45 sym2vol[volMod->getSymName()] = volMod;
46 }
47 }
48 }
49 }
50 }
51
52 // NOTE: for ITS sensors the local x and y are swapped
53 int lay = 0, hba = 0, sta = 0, ssta = 0, modd = 0, chip = 0;
54 for (int ich = 0; ich < geom->getNumberOfChips(); ich++) {
55 geom->getChipId(ich, lay, hba, sta, ssta, modd, chip);
56 GlobalLabel lbl(det, ich, true);
57 AlignableVolume* parVol = sym2vol[modd < 0 ? geom->composeSymNameStave(lay, hba, sta) : geom->composeSymNameModule(lay, hba, sta, ssta, modd)];
58 if (!parVol) {
59 LOGP(fatal, "did not find parent for chip {}", ich);
60 }
61 int nch = modd < 0 ? geom->getNumberOfChipsPerStave(lay) : geom->getNumberOfChipsPerModule(lay);
62 int jch = ich % nch;
63 auto* chip = parVol->addChild<AlignableSensorITS>(geom->composeSymNameChip(lay, hba, sta, ssta, modd, jch), lbl);
64 chip->setSensorId(ich);
65 sensorMap[lbl] = chip;
66 }
67 return root;
68}
69
71{
72 uint32_t gLbl{0}, det{0};
74 AlignableVolume *volHB{nullptr}, *volSt{nullptr}, *volHSt{nullptr}, *volMod{nullptr};
75 std::unordered_map<std::string, AlignableVolume*> sym2vol;
76
77 auto root = std::make_unique<AlignableVolume>(geom->composeSymNameITS(), gLbl++, det, false);
78 sym2vol[root->getSymName()] = root.get();
79 for (int ilr = 0; ilr < geom->getNumberOfLayers(); ilr++) {
80 const bool isLayITS3 = (ilr < 3);
81 for (int ihb = 0; ihb < geom->getNumberOfHalfBarrels(); ihb++) {
82 volHB = root->addChild(geom->composeSymNameHalfBarrel(ilr, ihb, isLayITS3), gLbl++, det, false);
83 sym2vol[volHB->getSymName()] = volHB;
84 if (isLayITS3) {
85 volHB->setSensorId((2 * ilr) + ihb);
86 continue; // no deeper hierarchy for ITS3 layers
87 }
88 int nstavesHB = geom->getNumberOfStaves(ilr) / 2;
89 for (int ist = 0; ist < nstavesHB; ist++) {
90 volSt = volHB->addChild(geom->composeSymNameStave(ilr, ihb, ist), gLbl++, det, false);
91 sym2vol[volSt->getSymName()] = volSt;
92 for (int ihst = 0; ihst < geom->getNumberOfHalfStaves(ilr); ihst++) {
93 volHSt = volSt->addChild(geom->composeSymNameHalfStave(ilr, ihb, ist, ihst), gLbl++, det, false);
94 sym2vol[volHSt->getSymName()] = volHSt;
95 for (int imd = 0; imd < geom->getNumberOfModules(ilr); imd++) {
96 volMod = volHSt->addChild(geom->composeSymNameModule(ilr, ihb, ist, ihst, imd), gLbl++, det, false);
97 sym2vol[volMod->getSymName()] = volMod;
98 }
99 }
100 }
101 }
102 }
103
104 int lay = 0, hba = 0, sta = 0, ssta = 0, modd = 0, chip = 0;
105 for (int ich = 0; ich < geom->getNumberOfChips(); ich++) {
106 geom->getChipId(ich, lay, hba, sta, ssta, modd, chip);
107 const bool isLayITS3 = (lay < 3);
108 GlobalLabel lbl(det, ich, true);
109 if (isLayITS3) {
110 // ITS3 chips by construction do not have any DOFs still add them to have the measurment to alignable layer relation
111 AlignableVolume* parVol = sym2vol[geom->composeSymNameHalfBarrel(lay, hba, true)];
112 if (!parVol) {
113 LOGP(fatal, "did not find parent for chip {}", ich);
114 }
115 auto* tile = parVol->addChild<AlignableSensorIT3>(geom->composeSymNameChip(lay, hba, sta, ssta, modd, chip, true), lbl);
116 tile->setPseudo(true);
117 tile->setSensorId(ich);
118 sensorMap[lbl] = tile;
119 } else {
120 AlignableVolume* parVol = sym2vol[modd < 0 ? geom->composeSymNameStave(lay, hba, sta) : geom->composeSymNameModule(lay, hba, sta, ssta, modd)];
121 if (!parVol) {
122 LOGP(fatal, "did not find parent for chip {}", ich);
123 }
124 int nch = modd < 0 ? geom->getNumberOfChipsPerStave(lay) : geom->getNumberOfChipsPerModule(lay);
125 int jch = ich % nch;
126 auto* chip = parVol->addChild<AlignableSensorITS>(geom->composeSymNameChip(lay, hba, sta, ssta, modd, jch), lbl);
127 chip->setSensorId(ich);
128 sensorMap[lbl] = chip;
129 }
130 }
131 return root;
132}
133
134void AlignableSensorITS::defineMatrixL2G()
135{
136 // the chip volume is not the measurment plane, need to correct for the epitaxial layer
137 const auto* chipL2G = mPN->GetMatrix();
138 mL2G = *chipL2G;
140 TGeoTranslation tra(0., 0.5 * delta, 0.);
141 mL2G *= tra;
142}
143
144void AlignableSensorITS::defineMatrixT2L()
145{
146 double locA[3] = {-100., 0., 0.}, locB[3] = {100., 0., 0.}, gloA[3], gloB[3];
147 mL2G.LocalToMaster(locA, gloA);
148 mL2G.LocalToMaster(locB, gloB);
149 double dx = gloB[0] - gloA[0], dy = gloB[1] - gloA[1];
150 double t = (gloB[0] * dx + gloB[1] * dy) / (dx * dx + dy * dy);
151 double xp = gloB[0] - (dx * t), yp = gloB[1] - (dy * t);
152 double alp = std::atan2(yp, xp);
153 o2::math_utils::bringTo02Pid(alp);
154 mT2L.RotateZ(alp * TMath::RadToDeg()); // mT2L before is identity and afterwards rotated
155 const TGeoHMatrix l2gI = mL2G.Inverse();
156 mT2L.MultiplyLeft(l2gI);
157}
158
159void AlignableSensorITS::computeJacobianL2T(const double* posLoc, Matrix66& jac) const
160{
161 jac.setZero();
162 Eigen::Map<const Eigen::Matrix<double, 3, 3, Eigen::RowMajor>> rotT2L(mT2L.GetRotationMatrix());
163 Eigen::Matrix3d skew, rotL2T = rotT2L.transpose();
164 skew << 0, -posLoc[2], posLoc[1], posLoc[2], 0, -posLoc[0], -posLoc[1], posLoc[0], 0;
165 jac.topLeftCorner<3, 3>() = rotL2T;
166 jac.topRightCorner<3, 3>() = -rotL2T * skew;
167 jac.bottomRightCorner<3, 3>() = rotL2T;
168}
169
170void AlignableSensorIT3::defineMatrixL2G()
171{
172 mL2G = *mPN->GetMatrix();
173}
174
175void AlignableSensorIT3::defineMatrixT2L()
176{
177 double locA[3] = {-100., 0., 0.}, locB[3] = {100., 0., 0.}, gloA[3], gloB[3];
178 mL2G.LocalToMaster(locA, gloA);
179 mL2G.LocalToMaster(locB, gloB);
180 double dx = gloB[0] - gloA[0], dy = gloB[1] - gloA[1];
181 double t = (gloB[0] * dx + gloB[1] * dy) / (dx * dx + dy * dy);
182 double xp = gloB[0] - (dx * t), yp = gloB[1] - (dy * t);
183 double alp = std::atan2(yp, xp);
184 o2::math_utils::bringTo02Pid(alp);
185 mT2L.RotateZ(alp * TMath::RadToDeg());
186 const TGeoHMatrix l2gI = mL2G.Inverse();
187 mT2L.MultiplyLeft(l2gI);
188}
189
190void AlignableSensorIT3::computeJacobianL2T(const double* posLoc, Matrix66& jac) const
191{
192 jac.setZero();
193 Eigen::Map<const Eigen::Matrix<double, 3, 3, Eigen::RowMajor>> rotT2L(mT2L.GetRotationMatrix());
194 Eigen::Matrix3d skew, rotL2T = rotT2L.transpose();
195 skew << 0, -posLoc[2], posLoc[1], posLoc[2], 0, -posLoc[0], -posLoc[1], posLoc[0], 0;
196 jac.topLeftCorner<3, 3>() = rotL2T;
197 jac.topRightCorner<3, 3>() = -rotL2T * skew;
198 jac.bottomRightCorner<3, 3>() = rotL2T;
199}
200
201} // namespace o2::its3::align
Definition of the GeometryTGeo class.
Definition of the SegmentationAlpide class.
AlignableVolume * addChild(const char *symName, uint32_t label, uint32_t det, bool sens)
std::unique_ptr< AlignableVolume > Ptr
std::map< GlobalLabel, AlignableVolume * > SensorMapping
static GeometryTGeo * Instance()
static constexpr float SensorLayerThickness
static constexpr float SensorLayerThicknessEff
AlignableVolume::Ptr buildHierarchyITS(AlignableVolume::SensorMapping &sensorMap)
Eigen::Matrix< double, 6, 6 > Matrix66
AlignableVolume::Ptr buildHierarchyIT3(AlignableVolume::SensorMapping &sensorMap)