Skip to content

Commit 5e060aa

Browse files
committed
ALICE3-TRK: improving segmentation, dealing with different silicon depth and pixel size wrt the APTS response
1 parent 40a43e2 commit 5e060aa

File tree

10 files changed

+618
-1041
lines changed

10 files changed

+618
-1041
lines changed

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

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,17 @@ namespace o2::trk
2828
/// This is a work-in-progress code derived from the ITS2 and ITS3 segmentations.
2929
class SegmentationChip
3030
{
31-
// This class defines the segmenation of the TRK chips in the ALICE3 upgrade. We define
32-
// two coordinate systems, one width x,z detector local coordianates (cm) and
33-
// the more natural row,col layout: Also all the transformation between these
34-
// two. The class provides the transformation from the stave/layer/disk to TGeo
35-
// coordinates.
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
3638
// For the curved VD layers there exist three coordinate systems and one is transient.
3739
// 1. The global (curved) coordinate system. The chip's center of coordinate system is
3840
// defined at the the mid-point of the detector.
39-
// 2. The flat coordinate system. This is the tube segment projected onto a flat
41+
// 2. The local (flat) coordinate system. This is the tube segment projected onto a flat
4042
// surface. In the projection we implicitly assume that the inner and outer
4143
// stretch does not depend on the radius.
4244
// 3. The detector coordinate system. Defined by the row and column segmentation
@@ -58,17 +60,15 @@ class SegmentationChip
5860
static constexpr float PitchColVD{constants::VD::petal::layer::pitchZ};
5961
static constexpr float PitchRowVD{constants::VD::petal::layer::pitchX};
6062

61-
static constexpr float PitchColML{constants::moduleMLOT::chip::pitchZ};
62-
static constexpr float PitchRowML{constants::moduleMLOT::chip::pitchX};
63-
64-
static constexpr float PitchColOT{constants::moduleMLOT::chip::pitchZ};
65-
static constexpr float PitchRowOT{constants::moduleMLOT::chip::pitchX};
63+
static constexpr float PitchColMLOT{constants::moduleMLOT::chip::pitchZ};
64+
static constexpr float PitchRowMLOT{constants::moduleMLOT::chip::pitchX};
6665

6766
static constexpr float SensorLayerThicknessVD = {constants::VD::petal::layer::totalThickness}; // physical thickness of sensitive part = 30 um
6867
static constexpr float SensorLayerThicknessML = {constants::moduleMLOT::chip::totalThickness}; // physical thickness of sensitive part = 100 um
6968
static constexpr float SensorLayerThicknessOT = {constants::moduleMLOT::chip::totalThickness}; // physical thickness of sensitive part = 100 um
7069

71-
static constexpr float SiliconTickness = constants::silicon::thickness; // effective thickness of sensitive part
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
7272

7373
static constexpr std::array<double, constants::VD::petal::nLayers> radiiVD = constants::VD::petal::layer::radii;
7474

@@ -86,24 +86,25 @@ class SegmentationChip
8686
/// \param int subDetID Sub-detector ID (0 for VD, 1 for ML/OT)
8787
/// \param int layer Layer number (0 to 2 for VD, 0 to 7 for ML/OT)
8888
/// \param int disk Disk number (0 to 5 for VD)
89-
static bool globalToDetector(float xRow, float zCol, int& iRow, int& iCol, int subDetID, int layer, int disk) noexcept
89+
static bool localToDetector(float xRow, float zCol, int& iRow, int& iCol, int subDetID, int layer, int disk) noexcept
9090
{
9191
if (!isValidGlob(xRow, zCol, subDetID, layer)) {
92-
LOGP(info, "Global coordinates not valid: row = {} cm, col = {} cm", xRow, zCol);
92+
LOGP(debug, "Local coordinates not valid: row = {} cm, col = {} cm", xRow, zCol);
9393
return false;
9494
}
95+
localToDetectorUnchecked(xRow, zCol, iRow, iCol, subDetID, layer, disk);
9596

96-
globalToDetectorUnchecked(xRow, zCol, iRow, iCol, subDetID, layer, disk);
97+
LOG(debug) << "Result from localToDetectorUnchecked: xRow " << xRow << " -> iRow " << iRow << ", zCol " << zCol << " -> iCol " << iCol << " on subDetID, layer, disk: " << subDetID << " " << layer << " " << disk;
9798

9899
if (!isValidDet(iRow, iCol, subDetID, layer)) {
99100
iRow = iCol = -1;
100-
LOGP(info, "Detector coordinates not valid: iRow = {}, iCol = {}", iRow, iCol);
101+
LOGP(debug, "Detector coordinates not valid: iRow = {}, iCol = {}", iRow, iCol);
101102
return false;
102103
}
103104
return true;
104105
};
105106
/// same but w/o check for row/column range
106-
static void globalToDetectorUnchecked(float xRow, float zCol, int& iRow, int& iCol, int subDetID, int layer, int disk) noexcept
107+
static void localToDetectorUnchecked(float xRow, float zCol, int& iRow, int& iCol, int subDetID, int layer, int disk) noexcept
107108
{
108109
// convert to row/col w/o over/underflow check
109110
float pitchRow(0), pitchCol(0);
@@ -116,13 +117,13 @@ class SegmentationChip
116117
maxLength = constants::VD::petal::layer::length;
117118
// TODO: change this to use the layer and disk
118119
} else if (subDetID == 1 && layer <= 3) { // ML
119-
pitchRow = PitchRowML;
120-
pitchCol = PitchColML;
120+
pitchRow = PitchRowMLOT;
121+
pitchCol = PitchColMLOT;
121122
maxWidth = constants::ML::width;
122123
maxLength = constants::ML::length;
123124
} else if (subDetID == 1 && layer >= 4) { // OT
124-
pitchRow = PitchRowOT;
125-
pitchCol = PitchColOT;
125+
pitchRow = PitchRowMLOT;
126+
pitchCol = PitchColMLOT;
126127
maxWidth = constants::OT::width;
127128
maxLength = constants::OT::length;
128129
}
@@ -131,7 +132,7 @@ class SegmentationChip
131132
iCol = static_cast<int>(std::floor((zCol + maxLength / 2) / pitchCol));
132133
};
133134

134-
// Check global coordinates (cm) validity.
135+
// Check local coordinates (cm) validity.
135136
static constexpr bool isValidGlob(float x, float z, int subDetID, int layer) noexcept
136137
{
137138
float maxWidth(0), maxLength(0);
@@ -165,8 +166,7 @@ class SegmentationChip
165166
nRows = constants::OT::nRows;
166167
nCols = constants::OT::nCols;
167168
}
168-
return (row >= 0 && row < static_cast<float>(nRows) &&
169-
col >= 0 && col < static_cast<float>(nCols));
169+
return (row >= 0 && row < static_cast<float>(nRows) && col >= 0 && col < static_cast<float>(nCols));
170170
}
171171

172172
/// Transformation from Detector cell coordinates to Geant detector centered
@@ -182,34 +182,37 @@ class SegmentationChip
182182
/// \param int subDetID Sub-detector ID (0 for VD, 1 for ML/OT)
183183
/// \param int layer Layer number (0 to 2 for VD, 0 to 7 for ML/OT)
184184
/// \param int disk Disk number (0 to 5 for VD)
185-
static constexpr bool detectorToGlobal(int iRow, int iCol, float& xRow, float& zCol, int subDetID, int layer, int disk) noexcept
185+
static constexpr bool detectorToLocal(int iRow, int iCol, float& xRow, float& zCol, int subDetID, int layer, int disk) noexcept
186186
{
187-
if (!isValidDet(xRow, zCol, subDetID, layer)) {
187+
if (!isValidDet(iRow, iCol, subDetID, layer)) {
188188
LOGP(debug, "Detector coordinates not valid: iRow = {}, iCol = {}", iRow, iCol);
189189
return false;
190190
}
191-
detectorToGlobalUnchecked(iRow, iCol, xRow, zCol, subDetID, layer, disk);
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;
192193

193194
if (!isValidGlob(xRow, zCol, subDetID, layer)) {
194-
LOGP(debug, "Global coordinates not valid: row = {} cm, col = {} cm", xRow, zCol);
195+
LOGP(debug, "Local coordinates not valid: row = {} cm, col = {} cm", xRow, zCol);
195196
return false;
196197
}
197198
return true;
198199
};
199200

200-
// Same as detectorToGlobal w.o. checks.
201+
// Same as detectorToLocal w.o. checks.
201202
// We position ourself in the middle of the pixel.
202-
static void detectorToGlobalUnchecked(int& row, int& col, float xRow, float zCol, int subDetID, int layer, int disk) noexcept
203+
static void detectorToLocalUnchecked(int row, int col, float& xRow, float& zCol, int subDetID, int layer, int disk) noexcept
203204
{
205+
/// xRow = half chip width - iRow(center) * pitch
206+
/// zCol = iCol * pitch - half chip lenght
204207
if (subDetID == 0) {
205-
xRow = -(row + 0.5f) * PitchRowVD + constants::VD::petal::layer::width[layer] / 2;
206-
zCol = (col + 0.5f) * PitchColVD - constants::VD::petal::layer::length / 2;
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);
207210
} else if (subDetID == 1 && layer <= 3) { // ML
208-
xRow = -(row + 0.5f) * PitchRowML + constants::ML::width / 2;
209-
zCol = (col + 0.5f) * PitchColML - constants::ML::length / 2;
211+
xRow = 0.5 * (constants::ML::width - PitchRowMLOT) - (row * PitchRowMLOT);
212+
zCol = col * PitchRowMLOT + 0.5 * (PitchRowMLOT - constants::ML::length);
210213
} else if (subDetID == 1 && layer >= 4) { // OT
211-
xRow = -(row + 0.5f) * PitchRowOT + constants::OT::width / 2;
212-
zCol = (col + 0.5f) * PitchColOT - constants::OT::length / 2;
214+
xRow = 0.5 * (constants::OT::width - PitchRowMLOT) - (row * PitchRowMLOT);
215+
zCol = col * PitchColMLOT + 0.5 * (PitchColMLOT - constants::OT::length);
213216
}
214217
}
215218

@@ -225,7 +228,6 @@ class SegmentationChip
225228
/// the center of the sensitive volume.
226229
/// \return math_utils::Vector2D<float>: x and y represent the detector local flat coordinates x and y
227230
// in cm with respect to the center of the sensitive volume.
228-
229231
static math_utils::Vector2D<float> curvedToFlat(const int layer, const float xCurved, const float yCurved) noexcept
230232
{
231233
// Align the flat surface with the curved survace of the original chip (and account for metal stack, TODO)
@@ -259,8 +261,22 @@ class SegmentationChip
259261
float yCurved = dist * std::sin(phi);
260262
return math_utils::Vector2D<float>(xCurved, yCurved);
261263
}
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+
}
262278
};
263279

264280
} // namespace o2::trk
265281

266-
#endif
282+
#endif

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

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,16 @@ constexpr double cm{1};
3030
constexpr double mu{1e-4};
3131
constexpr double mm{1e-1};
3232

33-
// namespace metalstack /// still to be defined
34-
// {
35-
// constexpr double thickness{5 * mu}; // physical thickness of the copper metal stack
36-
// }
37-
3833
namespace VD // TODO: add a primitive segmentation with more granularity wrt 1/4 layer = 1 chip
3934
{
35+
namespace silicon
36+
{
37+
constexpr double thickness{30 * mu}; // thickness of the silicon (should be 10 um epitaxial layer + 20 um substrate)?
38+
} // namespace silicon
39+
namespace metalstack
40+
{
41+
constexpr double thickness{0 * mu}; // thickness of the copper metal stack - for the moment it is not implemented
42+
} // namespace metalstack
4043
namespace petal
4144
{
4245
constexpr int nLayers{3}; // number of layers in each VD petal
@@ -45,12 +48,12 @@ namespace layer
4548
{
4649
constexpr double pitchX{10 * mu}; // pitch of the row
4750
constexpr double pitchZ{10 * mu}; // pitch of the column
48-
constexpr double totalThickness{30 * mu}; // total thickness of the chip
49-
constexpr std::array<double, nLayers> radii{0.5 * cm, 1.2 * cm, 2.5 * cm}; // width of the quarter of layer in cm
51+
constexpr double totalThickness{silicon::thickness + metalstack::thickness}; // total thickness of the chip
52+
constexpr std::array<double, nLayers> radii{0.5 * cm, 1.2 * cm, 2.5 * cm}; // radius of layer in cm
5053
constexpr std::array<double, nLayers> width{radii[0] * 2 * M_PI / 4, radii[1] * 2 * M_PI / 4, radii[2] * 2 * M_PI / 4}; // width of the quarter of layer in cm
5154
constexpr double length{50 * cm}; // length of the layer
5255
constexpr int nCols{static_cast<int>(length / pitchZ)}; // number of columns in the chip
53-
constexpr std::array<int, nLayers> nRows{static_cast<int>(width[0] / pitchX), static_cast<int>(width[1] / pitchX), static_cast<int>(width[2] / pitchX)}; // number of rows in the chip
56+
constexpr std::array<int, nLayers> nRows{static_cast<int>(width[0] / pitchX), static_cast<int>(width[1] / pitchX), static_cast<int>(width[2] / pitchX)}; // number of rows in the chip. For the moment is different for each layer since a siner segmentation in repetitive units is stil to be implemented
5457

5558
} // namespace layer
5659
namespace disk
@@ -62,16 +65,24 @@ constexpr double radiusOut{2.5 * cm};
6265
} // namespace VD
6366

6467
namespace moduleMLOT /// same for ML and OT for the moment
65-
{ /// TODO: account for different modules in case of change
68+
{ /// TODO: account for different modules in case of changes
69+
namespace silicon
70+
{
71+
constexpr double thickness{100 * mu}; // thickness of the silicon (should be 10 um epitaxial layer + 90 um substrate)?
72+
} // namespace silicon
73+
namespace metalstack
74+
{
75+
constexpr double thickness{0 * mu}; // thickness of the copper metal stack - for the moment it is not implemented
76+
} // namespace metalstack
6677
namespace chip
6778
{
68-
constexpr double width{25 * mm}; // width of the chip
69-
constexpr double length{32 * mm}; // length of the chip
70-
constexpr double pitchX{50 * mu}; // pitch of the row
71-
constexpr double pitchZ{50 * mu}; // pitch of the column
72-
constexpr int nRows{static_cast<int>(width / pitchX)}; // number of columns in the chip
73-
constexpr int nCold{static_cast<int>(length / pitchZ)}; // number of rows in the chipù
74-
constexpr double totalThickness{100 * mu}; // total thickness of the chip
79+
constexpr double width{25 * mm}; // width of the chip
80+
constexpr double length{32 * mm}; // length of the chip
81+
constexpr double pitchX{50 * mu}; // pitch of the row
82+
constexpr double pitchZ{50 * mu}; // pitch of the column
83+
constexpr int nRows{static_cast<int>(width / pitchX)}; // number of columns in the chip
84+
constexpr int nCols{static_cast<int>(length / pitchZ)}; // number of rows in the chip
85+
constexpr double totalThickness{silicon::thickness + metalstack::thickness}; // total thickness of the chip
7586
/// Set to 0 for the moment, to be adjusted with the actual design of the chip if needed
7687
static constexpr float PassiveEdgeReadOut = 0.f; // width of the readout edge (Passive bottom)
7788
static constexpr float PassiveEdgeTop = 0.f; // Passive area on top
@@ -86,7 +97,7 @@ constexpr double outerEdgeShortSide{0.1 * mm}; // gap between the chips and the
8697
constexpr double width{chip::width * 2 + gaps::interChips + 2 * gaps::outerEdgeLongSide}; // width of the module
8798
constexpr double length{chip::length * 4 + 3 * gaps::interChips + 2 * gaps::outerEdgeShortSide}; // length of the module
8899
constexpr int nRows{static_cast<int>(width / chip::pitchX)}; // number of columns in the module
89-
constexpr int nCold{static_cast<int>(length / chip::pitchZ)}; // number of rows in the module
100+
constexpr int nCols{static_cast<int>(length / chip::pitchZ)}; // number of rows in the module
90101
} // namespace moduleMLOT
91102

92103
namespace ML
@@ -98,17 +109,21 @@ constexpr int nCols{static_cast<int>(length / constants::moduleMLOT::chip::pitch
98109
} // namespace ML
99110

100111
namespace OT
101-
{
112+
{ //// TODO: add shorter lenght of the stave of L4
102113
constexpr double width{moduleMLOT::width * 2}; // width of the stave
103114
constexpr double length{moduleMLOT::length * 20}; // length of the stave
104115
constexpr int nRows{static_cast<int>(width / moduleMLOT::chip::pitchX)}; // number of rows in the stave
105116
constexpr int nCols{static_cast<int>(length / moduleMLOT::chip::pitchZ)}; // number of columns in the stave
106117
} // namespace OT
107118

108-
namespace silicon
119+
namespace apts /// parameters for the APTS response
109120
{
110-
constexpr double thickness{10 * mu}; // thickness of active material
111-
} // namespace silicon
121+
constexpr double pitchX{15.0 * mu};
122+
constexpr double pitchZ{15.0 * mu};
123+
constexpr double responseYShift{15.5 * mu};
124+
constexpr double thickness{45 * mu};
125+
} // namespace apts
126+
112127
} // namespace o2::trk::constants
113128

114-
#endif
129+
#endif

Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ TString GeometryTGeo::getMatrixPath(int index) const
266266
int subDetID, petalcase, disk, layer, stave, halfstave; //// TODO: add chips in a second step
267267
getChipID(index, subDetID, petalcase, disk, layer, stave, halfstave);
268268

269-
PrintChipID(index, subDetID, petalcase, disk, layer, stave, halfstave);
269+
// PrintChipID(index, subDetID, petalcase, disk, layer, stave, halfstave);
270270

271271
// TString path = "/cave_1/barrel_1/TRKV_2/TRKLayer0_1/TRKStave0_1/TRKChip0_1/TRKSensor0_1/"; /// dummy path, to be used for tests
272272
TString path = Form("/cave_1/barrel_1/%s_2/", GeometryTGeo::getTRKVolPattern());
@@ -709,4 +709,4 @@ void GeometryTGeo::Print(Option_t*) const
709709
}
710710

711711
} // namespace trk
712-
} // namespace o2
712+
} // namespace o2

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ o2_add_library(TRKSimulation
2424
PUBLIC_LINK_LIBRARIES O2::TRKBase
2525
O2::FT3Simulation
2626
O2::ITSMFTSimulation
27+
O2::DetectorsRaw
2728
O2::SimulationDataFormat)
2829

2930
o2_target_root_dictionary(TRKSimulation

0 commit comments

Comments
 (0)