Skip to content

Commit 8735573

Browse files
atrioloalibuild
andauthored
ALICE3-TRK: first version of working digitizer (#14619)
* ALICE3-TRK: correctly setting the path to retrieve matrices from the geometry * ALICE3-TRK: setting basis for digitization code - definition of a simple segmentation, adding methods to deal with the curved VD layers, adding chip response based on ITS2 and ITS3 codes, adding useful codes for parameters, digit containers, etc. * ALICE3-TRK: improving segmentation, dealing with different silicon depth and pixel size wrt the APTS response * ALICE3-TRK: adjusted curvedToFlat coordinate orientation * ALICE3-TRK: first version of complete digitizer. Now the digits are stored in the trkdigits.root file * ALICE3-TRK: fixing DigitROF setting * Please consider the following formatting changes * ALICE3-TRK: fixing copyright headers --------- Co-authored-by: ALICE Action Bot <alibuild@cern.ch>
1 parent dec2fe8 commit 8735573

File tree

17 files changed

+1395
-491
lines changed

17 files changed

+1395
-491
lines changed

Detectors/Upgrades/ALICE3/TRK/base/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
o2_add_library(TRKBase
1313
SOURCES src/GeometryTGeo.cxx
1414
src/TRKBaseParam.cxx
15+
src/SegmentationChip.cxx
1516
PUBLIC_LINK_LIBRARIES O2::DetectorsBase)
1617

1718
o2_target_root_dictionary(TRKBase
1819
HEADERS include/TRKBase/GeometryTGeo.h
19-
include/TRKBase/TRKBaseParam.h)
20+
include/TRKBase/TRKBaseParam.h
21+
include/TRKBase/SegmentationChip.h)

Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache
7373
void setOwner(bool v) { mOwner = v; }
7474

7575
void Print(Option_t* opt = "") const;
76-
void PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int halfstave, int indexRetrieved) const;
76+
void PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int halfstave) const;
7777

7878
int getLayer(int index) const;
7979
int getStave(int index) const;
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
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+
12+
/// \file SegmentationChip.h
13+
/// \brief Definition of the SegmentationChipclass
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+
24+
namespace o2::trk
25+
{
26+
27+
/// Segmentation and response for TRK chips in ALICE3 upgrade
28+
/// This is a work-in-progress code derived from the ITS2 and ITS3 segmentations.
29+
class SegmentationChip
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 three coordinate systems and one is transient.
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 (flat) coordinate system. This is the tube segment projected onto a flat
42+
// surface. In the projection we implicitly assume that the inner and outer
43+
// stretch does not depend on the radius.
44+
// 3. The detector coordinate system. Defined by the row and column segmentation
45+
// defined at the upper edge in the flat coord.
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;
58+
constexpr SegmentationChip& operator=(SegmentationChip&&) = delete;
59+
60+
static constexpr float PitchColVD{constants::VD::petal::layer::pitchZ};
61+
static constexpr float PitchRowVD{constants::VD::petal::layer::pitchX};
62+
63+
static constexpr float PitchColMLOT{constants::moduleMLOT::chip::pitchZ};
64+
static constexpr float PitchRowMLOT{constants::moduleMLOT::chip::pitchX};
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+
75+
/// Transformation from Geant detector centered local coordinates (cm) to
76+
/// Pixel cell numbers iRow and iCol.
77+
/// Returns kTRUE if point x,z is inside sensitive volume, kFALSE otherwise.
78+
/// A value of -1 for iRow or iCol indicates that this point is outside of the
79+
/// detector segmentation as defined.
80+
/// \param float x Detector local coordinate x in cm with respect to
81+
/// the center of the sensitive volume.
82+
/// \param float z Detector local coordinate z in cm with respect to
83+
/// the center of the sensitive volulme.
84+
/// \param int iRow Detector x cell coordinate. Has the range 0 <= iRow < mNumberOfRows
85+
/// \param int iCol Detector z cell coordinate. Has the range 0 <= iCol < mNumberOfColumns
86+
/// \param int subDetID Sub-detector ID (0 for VD, 1 for ML/OT)
87+
/// \param int layer Layer number (0 to 2 for VD, 0 to 7 for ML/OT)
88+
/// \param int disk Disk number (0 to 5 for VD)
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+
};
106+
/// same but w/o check for row/column range
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) { // OT
125+
pitchRow = PitchRowMLOT;
126+
pitchCol = PitchColMLOT;
127+
maxWidth = constants::OT::width;
128+
maxLength = constants::OT::length;
129+
}
130+
// convert to row/col
131+
iRow = static_cast<int>(std::floor((maxWidth / 2 - xRow) / pitchRow));
132+
iCol = static_cast<int>(std::floor((zCol + maxLength / 2) / pitchCol));
133+
};
134+
135+
// Check local coordinates (cm) validity.
136+
static constexpr bool isValidGlob(float x, float z, int subDetID, int layer) noexcept
137+
{
138+
float maxWidth(0), maxLength(0);
139+
if (subDetID == 0) {
140+
maxWidth = constants::VD::petal::layer::width[layer];
141+
maxLength = constants::VD::petal::layer::length;
142+
// TODO: change this to use the layer and disk
143+
} else if (subDetID == 1 && layer <= 3) { // ML
144+
maxWidth = constants::ML::width;
145+
maxLength = constants::ML::length;
146+
} else if (subDetID == 1 && layer >= 4) { // OT
147+
maxWidth = constants::OT::width;
148+
maxLength = constants::OT::length;
149+
}
150+
return (-maxWidth / 2 < x && x < maxWidth / 2 && -maxLength / 2 < z && z < maxLength / 2);
151+
}
152+
153+
// Check detector coordinates validity.
154+
static constexpr bool isValidDet(float row, float col, int subDetID, int layer) noexcept
155+
{
156+
// Check if the row and column are within the valid range
157+
int nRows(0), nCols(0);
158+
if (subDetID == 0) {
159+
nRows = constants::VD::petal::layer::nRows[layer];
160+
nCols = constants::VD::petal::layer::nCols;
161+
// TODO: change this to use the layer and disk
162+
} else if (subDetID == 1 && layer <= 3) { // ML
163+
nRows = constants::ML::nRows;
164+
nCols = constants::ML::nCols;
165+
} else if (subDetID == 1 && layer >= 4) { // OT
166+
nRows = constants::OT::nRows;
167+
nCols = constants::OT::nCols;
168+
}
169+
return (row >= 0 && row < static_cast<float>(nRows) && col >= 0 && col < static_cast<float>(nCols));
170+
}
171+
172+
/// Transformation from Detector cell coordinates to Geant detector centered
173+
/// local coordinates (cm)
174+
/// \param int iRow Detector x cell coordinate.
175+
/// \param int iCol Detector z cell coordinate.
176+
/// \param float x Detector local coordinate x in cm with respect to the
177+
/// center of the sensitive volume.
178+
/// \param float z Detector local coordinate z in cm with respect to the
179+
/// center of the sensitive volume.
180+
/// If iRow and or iCol is outside of the segmentation range a value of -0.5*Dx()
181+
/// or -0.5*Dz() is returned.
182+
/// \param int subDetID Sub-detector ID (0 for VD, 1 for ML/OT)
183+
/// \param int layer Layer number (0 to 2 for VD, 0 to 7 for ML/OT)
184+
/// \param int disk Disk number (0 to 5 for VD)
185+
static constexpr bool detectorToLocal(int iRow, int iCol, float& xRow, float& zCol, int subDetID, int layer, int disk) noexcept
186+
{
187+
if (!isValidDet(iRow, iCol, subDetID, layer)) {
188+
LOGP(debug, "Detector coordinates not valid: iRow = {}, iCol = {}", iRow, iCol);
189+
return false;
190+
}
191+
detectorToLocalUnchecked(iRow, iCol, xRow, zCol, subDetID, layer, disk);
192+
LOG(debug) << "Result from detectorToLocalUnchecked: iRow " << iRow << " -> xRow " << xRow << ", iCol " << iCol << " -> zCol " << zCol << " on subDetID, layer, disk: " << subDetID << " " << layer << " " << disk;
193+
194+
if (!isValidGlob(xRow, zCol, subDetID, layer)) {
195+
LOGP(debug, "Local coordinates not valid: row = {} cm, col = {} cm", xRow, zCol);
196+
return false;
197+
}
198+
return true;
199+
};
200+
201+
// Same as detectorToLocal w.o. checks.
202+
// We position ourself in the middle of the pixel.
203+
static void detectorToLocalUnchecked(int row, int col, float& xRow, float& zCol, int subDetID, int layer, int disk) noexcept
204+
{
205+
/// xRow = half chip width - iRow(center) * pitch
206+
/// zCol = iCol * pitch - half chip lenght
207+
if (subDetID == 0) {
208+
xRow = 0.5 * (constants::VD::petal::layer::width[layer] - PitchRowVD) - (row * PitchRowVD);
209+
zCol = col * PitchColVD + 0.5 * (PitchColVD - constants::VD::petal::layer::length);
210+
} else if (subDetID == 1 && layer <= 3) { // ML
211+
xRow = 0.5 * (constants::ML::width - PitchRowMLOT) - (row * PitchRowMLOT);
212+
zCol = col * PitchRowMLOT + 0.5 * (PitchRowMLOT - constants::ML::length);
213+
} else if (subDetID == 1 && layer >= 4) { // OT
214+
xRow = 0.5 * (constants::OT::width - PitchRowMLOT) - (row * PitchRowMLOT);
215+
zCol = col * PitchColMLOT + 0.5 * (PitchColMLOT - constants::OT::length);
216+
}
217+
}
218+
219+
/// Transformation from the curved surface to a flat surface.
220+
/// Additionally a shift in the flat coordinates must be applied because
221+
/// the center of the TGeoShap when projected will be higher than the
222+
/// physical thickness of the chip. Thus we shift the projected center
223+
/// down by this difference to align the coordinate systems.
224+
/// \param layer VD layer number
225+
/// \param xCurved Detector local curved coordinate x in cm with respect to
226+
/// the center of the sensitive volume.
227+
/// \param yCurved Detector local curved coordinate y in cm with respect to
228+
/// the center of the sensitive volume.
229+
/// \return math_utils::Vector2D<float>: x and y represent the detector local flat coordinates x and y
230+
// in cm with respect to the center of the sensitive volume.
231+
static math_utils::Vector2D<float> curvedToFlat(const int layer, const float xCurved, const float yCurved) noexcept
232+
{
233+
// Align the flat surface with the curved survace of the original chip (and account for metal stack, TODO)
234+
float dist = std::hypot(xCurved, yCurved);
235+
float phi = std::atan2(yCurved, xCurved);
236+
237+
// the y position is in the silicon volume however we need the chip volume (silicon+metalstack)
238+
// this is accounted by a y shift
239+
float xFlat = constants::VD::petal::layer::radii[layer] * phi; /// this is equal to the circumference segment covered between y=0 and the phi angle
240+
float yFlat = constants::VD::petal::layer::radii[layer] - dist;
241+
return math_utils::Vector2D<float>(xFlat, yFlat);
242+
}
243+
244+
/// Transformation from the flat surface to a curved surface
245+
/// It works only if the detector is not rototraslated.
246+
/// \param layer VD layer number
247+
/// \param xFlat Detector local flat coordinate x in cm with respect to
248+
/// the center of the sensitive volume.
249+
/// \param yFlat Detector local flat coordinate y in cm with respect to
250+
/// the center of the sensitive volume.
251+
/// \return math_utils::Vector2D<float>: x and y represent the detector local curved coordinates x and y
252+
// in cm with respect to the center of the sensitive volume.
253+
static constexpr math_utils::Vector2D<float> flatToCurved(int layer, float xFlat, float yFlat) noexcept
254+
{
255+
// Revert the curvedToFlat transformation
256+
float dist = constants::VD::petal::layer::radii[layer] - yFlat;
257+
float phi = xFlat / constants::VD::petal::layer::radii[layer];
258+
// the y position is in the chip volume however we need the silicon volume
259+
// this is accounted by a -y shift
260+
float xCurved = dist * std::cos(phi);
261+
float yCurved = dist * std::sin(phi);
262+
return math_utils::Vector2D<float>(xCurved, yCurved);
263+
}
264+
265+
/// Print segmentation info
266+
static const void Print() noexcept
267+
{
268+
LOG(info) << "Number of rows:\nVD L0: " << constants::VD::petal::layer::nRows[0]
269+
<< "\nVD L1: " << constants::VD::petal::layer::nRows[1]
270+
<< "\nVD L2: " << constants::VD::petal::layer::nRows[2]
271+
<< "\nML stave: " << constants::ML::nRows
272+
<< "\nOT stave: " << constants::OT::nRows;
273+
274+
LOG(info) << "Number of cols:\nVD: " << constants::VD::petal::layer::nCols
275+
<< "\nML stave: " << constants::ML::nCols
276+
<< "\nOT stave: " << constants::OT::nCols;
277+
}
278+
};
279+
280+
} // namespace o2::trk
281+
282+
#endif

0 commit comments

Comments
 (0)