Project
Loading...
Searching...
No Matches
SegmentationChip.h
Go to the documentation of this file.
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
14
15#ifndef ALICEO2_TRK_SEGMENTATIONCHIP_H_
16#define ALICEO2_TRK_SEGMENTATIONCHIP_H_
17
18#include <type_traits>
19#include <fairlogger/Logger.h>
20
21#include "MathUtils/Cartesian.h"
22#include "TRKBase/Specs.h"
23
24namespace o2::trk
25{
26
30{
31 // This class defines the segmenation of the TRK chips in the ALICE3 upgrade.
32 // The "global coordinate system" refers to the hit position in cm in the global coordinate system centered in 0,0,0
33 // The "local coordinate system" refers to the hit position in cm in the coordinate system of the sensor, which
34 // is centered in 0,0,0 in the case of curved layers, and in the middle of the chip in the case of flat layers
35 // The "detector coordinate system" refers to the hit position in row,col inside the sensor
36 // This class provides the transformations from the local and detector coordinate systems
37 // The conversion between global and local coordinate systems is operated by the transformation matrices
38 // For the curved VD layers there exist four coordinate systems.
39 // 1. The global (curved) coordinate system. The chip's center of coordinate system is
40 // defined at the the mid-point of the detector.
41 // 2. The local (curved) coordinate system, centered in 0,0,0.
42 // 3. The local (flat) coordinate system. This is the tube segment projected onto a flat
43 // surface, centered in the middle of the chip, with the y axis pointing towards the interaction point.
44 // In the projection we implicitly assume that the inner and outer stretch does not depend on the radius.
45 // 4. The detector coordinate system. Defined by the row and column segmentation.
46 // For the flat ML and OT layers, there exist two coordinate systems:
47 // 1. The global (flat) coordinate system. The chip's center of coordinate system is
48 // defined at the the mid-point of the detector.
49 // 2. The detector coordinate system. Defined by the row and column segmentation.
50 // TODO: add segmentation for VD disks
51
52 public:
53 constexpr SegmentationChip() = default;
54 ~SegmentationChip() = default;
55 constexpr SegmentationChip(const SegmentationChip&) = default;
56 constexpr SegmentationChip(SegmentationChip&&) = delete;
57 constexpr SegmentationChip& operator=(const SegmentationChip&) = default;
59
60 static constexpr float PitchColVD{constants::VD::petal::layer::pitchZ};
61 static constexpr float PitchRowVD{constants::VD::petal::layer::pitchX};
62
65
66 static constexpr float SensorLayerThicknessVD = {constants::VD::petal::layer::totalThickness}; // physical thickness of sensitive part = 30 um
67 static constexpr float SensorLayerThicknessML = {constants::moduleMLOT::chip::totalThickness}; // physical thickness of sensitive part = 100 um
68 static constexpr float SensorLayerThicknessOT = {constants::moduleMLOT::chip::totalThickness}; // physical thickness of sensitive part = 100 um
69
70 static constexpr float SiliconThicknessVD = constants::VD::silicon::thickness; // effective thickness of sensitive part
71 static constexpr float SiliconThicknessMLOT = constants::moduleMLOT::silicon::thickness; // effective thickness of sensitive part
72
73 static constexpr std::array<double, constants::VD::petal::nLayers> radiiVD = constants::VD::petal::layer::radii;
74
89 static bool localToDetector(float xRow, float zCol, int& iRow, int& iCol, int subDetID, int layer, int disk) noexcept
90 {
91 if (!isValidGlob(xRow, zCol, subDetID, layer)) {
92 LOGP(debug, "Local coordinates not valid: row = {} cm, col = {} cm", xRow, zCol);
93 return false;
94 }
95 localToDetectorUnchecked(xRow, zCol, iRow, iCol, subDetID, layer, disk);
96
97 LOG(debug) << "Result from localToDetectorUnchecked: xRow " << xRow << " -> iRow " << iRow << ", zCol " << zCol << " -> iCol " << iCol << " on subDetID, layer, disk: " << subDetID << " " << layer << " " << disk;
98
99 if (!isValidDet(iRow, iCol, subDetID, layer)) {
100 iRow = iCol = -1;
101 LOGP(debug, "Detector coordinates not valid: iRow = {}, iCol = {}", iRow, iCol);
102 return false;
103 }
104 return true;
105 };
107 static void localToDetectorUnchecked(float xRow, float zCol, int& iRow, int& iCol, int subDetID, int layer, int disk) noexcept
108 {
109 // convert to row/col w/o over/underflow check
110 float pitchRow(0), pitchCol(0);
111 float maxWidth(0), maxLength(0);
112
113 if (subDetID == 0) {
114 pitchRow = PitchRowVD;
115 pitchCol = PitchColVD;
116 maxWidth = constants::VD::petal::layer::width[layer];
117 maxLength = constants::VD::petal::layer::length;
118 // TODO: change this to use the layer and disk
119 } else if (subDetID == 1 && layer <= 3) { // ML
120 pitchRow = PitchRowMLOT;
121 pitchCol = PitchColMLOT;
122 maxWidth = constants::ML::width;
123 maxLength = constants::ML::length;
124 } else if (subDetID == 1 && layer == 4) { // ML/OT (mixed layer, length = ML but staggered as OT)
125 pitchRow = PitchRowMLOT;
126 pitchCol = PitchColMLOT;
128 maxLength = constants::ML::length;
129 } else if (subDetID == 1 && layer > 4) { // OT
130 pitchRow = PitchRowMLOT;
131 pitchCol = PitchColMLOT;
134 }
135 // convert to row/col
136 iRow = static_cast<int>(((maxWidth / 2 - xRow) / pitchRow));
137 iCol = static_cast<int>(((zCol + maxLength / 2) / pitchCol));
138 };
139
140 // Check local coordinates (cm) validity.
141 static constexpr bool isValidGlob(float x, float z, int subDetID, int layer) noexcept
142 {
143 float maxWidth(0), maxLength(0);
144 if (subDetID == 0) {
145 maxWidth = constants::VD::petal::layer::width[layer];
146 maxLength = constants::VD::petal::layer::length;
147 // TODO: change this to use the layer and disk
148 } else if (subDetID == 1 && layer <= 3) { // ML
149 maxWidth = constants::ML::width;
150 maxLength = constants::ML::length;
151 } else if (subDetID == 1 && layer == 4) { // ML/OT (mixed layer, length = ML but staggered as OT)
153 maxLength = constants::ML::length;
154 } else if (subDetID == 1 && layer > 4) { // OT
157 }
158 return (-maxWidth / 2 < x && x < maxWidth / 2 && -maxLength / 2 < z && z < maxLength / 2);
159 }
160
161 // Check detector coordinates validity.
162 static constexpr bool isValidDet(float row, float col, int subDetID, int layer) noexcept
163 {
164 // Check if the row and column are within the valid range
165 int nRows(0), nCols(0);
166 if (subDetID == 0) {
167 nRows = constants::VD::petal::layer::nRows[layer];
168 nCols = constants::VD::petal::layer::nCols;
169 // TODO: change this to use the layer and disk
170 } else if (subDetID == 1 && layer <= 3) { // ML
171 nRows = constants::ML::nRows;
172 nCols = constants::ML::nCols;
173 } else if (subDetID == 1 && layer == 4) { // ML/OT (mixed layer, length = ML but staggered as OT)
175 nCols = constants::ML::nCols;
176 } else if (subDetID == 1 && layer > 4) { // OT
179 }
180 return (row >= 0 && row < static_cast<float>(nRows) && col >= 0 && col < static_cast<float>(nCols));
181 }
182
196 static constexpr bool detectorToLocal(int iRow, int iCol, float& xRow, float& zCol, int subDetID, int layer, int disk) noexcept
197 {
198 if (!isValidDet(iRow, iCol, subDetID, layer)) {
199 LOGP(debug, "Detector coordinates not valid: iRow = {}, iCol = {}", iRow, iCol);
200 return false;
201 }
202 detectorToLocalUnchecked(iRow, iCol, xRow, zCol, subDetID, layer, disk);
203 LOG(debug) << "Result from detectorToLocalUnchecked: iRow " << iRow << " -> xRow " << xRow << ", iCol " << iCol << " -> zCol " << zCol << " on subDetID, layer, disk: " << subDetID << " " << layer << " " << disk;
204
205 if (!isValidGlob(xRow, zCol, subDetID, layer)) {
206 LOGP(debug, "Local coordinates not valid: row = {} cm, col = {} cm", xRow, zCol);
207 return false;
208 }
209 return true;
210 };
211
212 // Same as detectorToLocal w.o. checks.
213 // We position ourself in the middle of the pixel.
214 static void detectorToLocalUnchecked(int row, int col, float& xRow, float& zCol, int subDetID, int layer, int disk) noexcept
215 {
218 if (subDetID == 0) {
219 xRow = 0.5 * (constants::VD::petal::layer::width[layer] - PitchRowVD) - (row * PitchRowVD);
220 zCol = col * PitchColVD + 0.5 * (PitchColVD - constants::VD::petal::layer::length);
221 } else if (subDetID == 1 && layer <= 3) { // ML
222 xRow = 0.5 * (constants::ML::width - PitchRowMLOT) - (row * PitchRowMLOT);
224 } else if (subDetID == 1 && layer == 4) { // ML/OT (mixed layer, length = ML but staggered as OT)
227 } else if (subDetID == 1 && layer > 4) { // OT
230 }
231 }
232
244 // in cm with respect to the center of the sensitive volume.
245 static math_utils::Vector2D<float> curvedToFlat(const int layer, const float xCurved, const float yCurved) noexcept
246 {
247 // Align the flat surface with the curved survace of the original chip (and account for metal stack, TODO)
248 float dist = std::hypot(xCurved, yCurved);
249 float phi = std::atan2(yCurved, xCurved);
250
251 // the y position is in the silicon volume however we need the chip volume (silicon+metalstack)
252 // this is accounted by a y shift
253 float xFlat = constants::VD::petal::layer::radii[layer] * phi;
254 float yFlat = constants::VD::petal::layer::radii[layer] - dist;
255 return math_utils::Vector2D<float>(xFlat, yFlat);
256 }
257
266 // in cm with respect to the center of the sensitive volume.
267 static constexpr math_utils::Vector2D<float> flatToCurved(int layer, float xFlat, float yFlat) noexcept
268 {
269 // Revert the curvedToFlat transformation
270 float dist = constants::VD::petal::layer::radii[layer] - yFlat;
271 float phi = xFlat / constants::VD::petal::layer::radii[layer];
272 // the y position is in the chip volume however we need the silicon volume
273 // this is accounted by a -y shift
274 float xCurved = dist * std::cos(phi);
275 float yCurved = dist * std::sin(phi);
276 return math_utils::Vector2D<float>(xCurved, yCurved);
277 }
278
280 static void Print() noexcept
281 {
282 LOG(info) << "Number of rows:\nVD L0: " << constants::VD::petal::layer::nRows[0]
283 << "\nVD L1: " << constants::VD::petal::layer::nRows[1]
284 << "\nVD L2: " << constants::VD::petal::layer::nRows[2]
285 << "\nML stave: " << constants::ML::nRows
286 << "\nOT half stave: " << constants::OT::halfstave::nRows;
287
288 LOG(info) << "Number of cols:\nVD: " << constants::VD::petal::layer::nCols
289 << "\nML stave: " << constants::ML::nCols
290 << "\nOT half stave: " << constants::OT::halfstave::nCols;
291
292 LOG(info) << "Pitch rows [cm]:\nVD: " << PitchRowVD
293 << "\nML stave: " << PitchRowMLOT
294 << "\nOT stave: " << PitchRowMLOT;
295
296 LOG(info) << "Pitch cols [cm]:\nVD: " << PitchColVD
297 << "\nML stave: " << PitchColMLOT
298 << "\nOT stave: " << PitchColMLOT;
299 }
300};
301
302} // namespace o2::trk
303
304#endif
uint32_t col
Definition RawData.h:4
specs of the ALICE3 TRK
std::ostringstream debug
static void localToDetectorUnchecked(float xRow, float zCol, int &iRow, int &iCol, int subDetID, int layer, int disk) noexcept
same but w/o check for row/column range
static constexpr math_utils::Vector2D< float > flatToCurved(int layer, float xFlat, float yFlat) noexcept
static constexpr float SiliconThicknessVD
static constexpr float SensorLayerThicknessOT
static constexpr bool detectorToLocal(int iRow, int iCol, float &xRow, float &zCol, int subDetID, int layer, int disk) noexcept
constexpr SegmentationChip()=default
static void detectorToLocalUnchecked(int row, int col, float &xRow, float &zCol, int subDetID, int layer, int disk) noexcept
constexpr SegmentationChip(SegmentationChip &&)=delete
static constexpr float SensorLayerThicknessML
static constexpr float SensorLayerThicknessVD
static constexpr bool isValidGlob(float x, float z, int subDetID, int layer) noexcept
static constexpr float PitchColVD
static constexpr bool isValidDet(float row, float col, int subDetID, int layer) noexcept
constexpr SegmentationChip & operator=(SegmentationChip &&)=delete
static bool localToDetector(float xRow, float zCol, int &iRow, int &iCol, int subDetID, int layer, int disk) noexcept
static constexpr float PitchColMLOT
static constexpr float PitchRowMLOT
static constexpr std::array< double, constants::VD::petal::nLayers > radiiVD
static void Print() noexcept
Print segmentation info.
static constexpr float PitchRowVD
constexpr SegmentationChip & operator=(const SegmentationChip &)=default
constexpr SegmentationChip(const SegmentationChip &)=default
static constexpr float SiliconThicknessMLOT
static math_utils::Vector2D< float > curvedToFlat(const int layer, const float xCurved, const float yCurved) noexcept
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
constexpr double length
Definition Specs.h:107
constexpr int nRows
Definition Specs.h:108
constexpr double width
Definition Specs.h:105
constexpr int nCols
Definition Specs.h:109
constexpr double thickness
Definition Specs.h:37
constexpr double totalThickness
Definition Specs.h:85
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< int > row