ATLAS Offline Software
Loading...
Searching...
No Matches
PixelDiodeMatrix.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
8
9#include <cassert>
10#include <utility>
11
12namespace InDetDD {
13
14std::shared_ptr<const PixelDiodeMatrix> PixelDiodeMatrix::construct(double phiWidth, double etaWidth)
15{
16 class Helper : public PixelDiodeMatrix{};
17 std::shared_ptr<PixelDiodeMatrix> ptr = std::make_shared<Helper>();
18 ptr->initialize(phiWidth, etaWidth);
19 return ptr;
20}
21
23{
28 m_phiCells = 1;
29 m_etaCells = 1;
30 m_direction = phiDir; // Irrelevant
31 m_numCells = 0;
32 m_lowerCell = nullptr;
33 m_middleCells = nullptr;
34 m_upperCell = nullptr;
35 m_singleCell = true;
36}
37
38std::shared_ptr<const PixelDiodeMatrix> PixelDiodeMatrix::construct(Direction direction, // phi or eta
39 std::shared_ptr<const PixelDiodeMatrix> lowerCell,
40 std::shared_ptr<const PixelDiodeMatrix> middleCells,
41 int numCells,
42 std::shared_ptr<const PixelDiodeMatrix> upperCell)
43{
44 class Helper : public PixelDiodeMatrix{};
45 std::shared_ptr<PixelDiodeMatrix> ptr = std::make_shared<Helper>();
46 ptr->initialize(direction,
47 std::move(lowerCell),
48 std::move(middleCells),
49 numCells,
50 std::move(upperCell));
51 return ptr;
52}
53
54void PixelDiodeMatrix::initialize(Direction direction, // phi or eta
55 std::shared_ptr<const PixelDiodeMatrix> lowerCell,
56 std::shared_ptr<const PixelDiodeMatrix> middleCells,
57 int numCells,
58 std::shared_ptr<const PixelDiodeMatrix> upperCell)
59{
60 m_phiWidth = 0;
61 m_etaWidth = 0;
62 m_phiCells = 0;
63 m_etaCells = 0;
64 m_direction = direction;
65 m_numCells = numCells;
66 m_lowerCell = std::move(lowerCell);
67 m_middleCells = std::move(middleCells);
68 m_upperCell = std::move(upperCell);
69 m_singleCell = false;
70
71 // middleCells must be non zero.
72 assert(m_middleCells);
73
74 if (m_direction == phiDir) {
75
76 // In eta direction widths must be all the same.
77 if (m_middleCells){
78 m_etaWidth = m_middleCells->etaWidth();
79 m_etaCells = m_middleCells->etaCells();
80 }
81 // Check lower and upper are consistent
82 // TODO.
83
84 if (m_lowerCell) {
85 m_phiWidth += m_lowerCell->phiWidth();
86 m_phiCells += m_lowerCell->phiCells();
87 }
88
89 if (m_middleCells){
90 m_phiWidth += m_numCells * m_middleCells->phiWidth();
91 m_phiCells += m_numCells * m_middleCells->phiCells();
92 }
93
94 if (m_upperCell) {
95 m_phiWidth += m_upperCell->phiWidth();
96 m_phiCells += m_upperCell->phiCells();
97 }
98
99 } else { // eta Direction
100
101 // In phi direction widths must be all the same.
102 if (m_middleCells){
103 m_phiWidth = m_middleCells->phiWidth();
104 m_phiCells = m_middleCells->phiCells();
105 }
106 // Check lower and upper are consistent
107 // TODO.
108
109 if (m_lowerCell) {
110 m_etaWidth += m_lowerCell->etaWidth();
111 m_etaCells += m_lowerCell->etaCells();
112 }
113
114 if (m_middleCells){
115 m_etaWidth += m_numCells * m_middleCells->etaWidth();
116 m_etaCells += m_numCells * m_middleCells->etaCells();
117 }
118
119 if (m_upperCell) {
120 m_etaWidth += m_upperCell->etaWidth();
121 m_etaCells += m_upperCell->etaCells();
122 }
123
124 }
125
128}
129
130const PixelDiodeMatrix*
132
151
152{
153 using Trk::distPhi;
154 using Trk::distEta;
155
156 if (m_singleCell) {
157 return this;
158 }
159
160 double relPosDir = 0; // Relative position along m_direction
161 int startIndex = 0;
162 double pitch = 0;
163 double pitchInverse = 0;
164 int middleCells = 0;
165
166 if (m_direction == phiDir) {
167
168 relPosDir = relPosition[distPhi];
169 pitch = m_middleCells->phiWidth();
170 pitchInverse = m_middleCells->phiWidthInverse();
171 middleCells = m_middleCells->phiCells();
172
173 if (m_lowerCell) {
174 if (relPosDir < m_lowerCell->phiWidth()) {
175 return m_lowerCell->cellIdOfPosition(relPosition, cellId);
176 } else {
177 relPosDir -= m_lowerCell->phiWidth();
178 startIndex += m_lowerCell->phiCells();
179 }
180 }
181 } else { // etaDir
182
183 relPosDir = relPosition[distEta];
184 pitch = m_middleCells->etaWidth();
185 pitchInverse = m_middleCells->etaWidthInverse();
186 middleCells = m_middleCells->etaCells();
187
188 if (m_lowerCell) {
189 if (relPosDir < m_lowerCell->etaWidth()) {
190 return m_lowerCell->cellIdOfPosition(relPosition, cellId);
191 } else {
192 relPosDir -= m_lowerCell->etaWidth();
193 startIndex += m_lowerCell->etaCells();
194 }
195 }
196 }
197
198
199 int index = relPosDir * pitchInverse;
200
201 const PixelDiodeMatrix *nextCell{};
202
203 bool outOfBounds = index >= m_numCells;
204 if (m_upperCell != nullptr && outOfBounds) {
205 // We are in the upper cell.
207 nextCell = m_upperCell.get();
208 } else {
209 // We are in the middle cells
210 // Make sure its in range (in case of rounding errors)
211 if (outOfBounds) index = m_numCells - 1;
212 nextCell = m_middleCells.get();
213 }
214
215 if (index > 0) { // Make sure its in range (in case of rounding errors)
216 relPosDir -= index * pitch;
217 startIndex += index * middleCells;
218 }
219
220 int newPhiIndex = cellId.phiIndex();
221 int newEtaIndex = cellId.etaIndex();
222 const PixelDiodeMatrix *cell{};
223
224 if (m_direction == phiDir) {
225 if (nextCell->singleCell()) {
226 newPhiIndex += startIndex;
227 cell = nextCell;
228 } else {
229 Amg::Vector2D newRelPos(relPosDir, relPosition[distEta]);
230 SiCellId relId(0,0);
231 cell = nextCell->cellIdOfPosition(newRelPos, relId);
232 newPhiIndex += startIndex + relId.phiIndex();
233 newEtaIndex += relId.etaIndex();
234 }
235 } else {
236 if (nextCell->singleCell()) {
237 newEtaIndex += startIndex;
238 cell = nextCell;
239 } else {
240 Amg::Vector2D newRelPos(relPosition[distPhi], relPosDir);
241 SiCellId relId(0,0);
242 cell = nextCell->cellIdOfPosition(newRelPos, relId);
243 newPhiIndex += relId.phiIndex();
244 newEtaIndex += startIndex + relId.etaIndex();
245 }
246 }
247
248 cellId = SiCellId(newPhiIndex, newEtaIndex);
249 return cell;
250}
251
252
253
254const PixelDiodeMatrix *
255PixelDiodeMatrix::positionOfCell(const PixelDiodeMatrix *matrix, const SiCellId & cellId, Amg::Vector2D & dest_position)
256
257
271
272{
273 using Trk::distPhi;
274 using Trk::distEta;
275 Amg::Vector2D position{
276 -matrix->phiHalfWidth(),
277 -matrix->etaHalfWidth()
278 };
279
280 int rel_phi_index = cellId.phiIndex();
281 int rel_eta_index = cellId.etaIndex();
282 for( ;!matrix->m_singleCell; ) {
283
284 int relIndex = 0; // Relative index along m_direction
285 double pitch = 0;
286 int nMiddleCells = 0;
287 double startPos = 0;
288 const auto direction = matrix->m_direction;
289
290 if (direction == PixelDiodeMatrix::phiDir) {
291
292 relIndex = rel_phi_index;
293
294 const PixelDiodeMatrix *lowerCell = matrix->m_lowerCell.get();
295 if (lowerCell) {
296 if (relIndex < lowerCell->phiCells()) {
297 matrix = lowerCell;
298 continue;
299 } else {
300 relIndex -= lowerCell->phiCells();
301 startPos += lowerCell->phiWidth();
302 }
303 }
304 const PixelDiodeMatrix *middleCells = matrix->m_middleCells.get();
305 assert(middleCells);
306 pitch = middleCells->phiWidth();
307 nMiddleCells = middleCells->phiCells();
308
309 } else { // etaDir
310
311 relIndex = rel_eta_index;
312 const PixelDiodeMatrix *lowerCell = matrix->m_lowerCell.get();
313 if (lowerCell) {
314 if (relIndex < lowerCell->etaCells()) {
315 matrix = lowerCell;
316 continue;
317 } else {
318 relIndex -= lowerCell->etaCells();
319 startPos += lowerCell->etaWidth();
320 }
321 }
322 const PixelDiodeMatrix *middleCells = matrix->m_middleCells.get();
323 assert(middleCells);
324 pitch = middleCells->etaWidth();
325 nMiddleCells = middleCells->etaCells();
326
327 }
328
329 int index = std::min(relIndex / nMiddleCells,matrix->m_numCells); // @TODO upper bound correct ?
330 relIndex -= index * nMiddleCells;
331 startPos += index * pitch;
332
333 matrix = (matrix->m_upperCell && index == matrix->m_numCells ) ? matrix->m_upperCell.get() : matrix->m_middleCells.get();
334
335 if (direction == PixelDiodeMatrix::phiDir) {
336 rel_phi_index = relIndex;
337 position[distPhi] += startPos;
338 } else {
339 rel_eta_index = relIndex;
340 position[distEta] += startPos;
341 }
342 }
343 position[distPhi] += matrix->phiHalfWidth();
344 position[distEta] += matrix->etaHalfWidth();
345 dest_position = position;
346 return matrix;
347}
348
349std::string
351{
352 std::string prefix(level, ' ');
353
354 // base case: single cell
355 if (m_singleCell) {
356 std::string cellSize = "";
357 cellSize += prefix + "phi: " + std::to_string(m_phiWidth) + "\n";
358 cellSize += prefix + "eta: " + std::to_string(m_etaWidth) + "\n";
359 return cellSize;
360 }
361
362 std::string cellContent = "";
363
364 if (m_lowerCell == nullptr && m_middleCells == nullptr && m_upperCell == nullptr) {
365 cellContent += prefix + "completly empty (WARNING: there should always be at least one cell!)\n";
366 return cellContent;
367 }
368
369 cellContent += prefix + "direction: ";
370 if (m_direction == phiDir) { cellContent += "phi\n"; }
371 else if (m_direction == etaDir) { cellContent += "eta\n"; }
372 else { cellContent += "unknown\n"; }
373
374 // recursive call for nested cells
375 if (m_lowerCell != nullptr) {
376 cellContent += prefix + "lowerCell: \n";
377 cellContent += m_lowerCell->createDebugStringRepr(level + 1);
378 }
379 if (m_middleCells != nullptr) {
380 cellContent += prefix + "middleCells: " + std::to_string(m_numCells) + "x :\n";
381 cellContent += m_middleCells->createDebugStringRepr(level + 1);
382 }
383 if (m_upperCell != nullptr) {
384 cellContent += prefix + "upperCell: \n";
385 cellContent += m_upperCell->createDebugStringRepr(level + 1);
386 }
387
388 return cellContent;
389}
390
391} // end namespace
Class used to describe the segmentation of the pixel and allow for conversion between cell id and pos...
std::shared_ptr< const PixelDiodeMatrix > m_upperCell
const PixelDiodeMatrix * cellIdOfPosition(const Amg::Vector2D &position, SiCellId &cellId) const
Return cell Id corresponding to a relative position within the matrix.
std::shared_ptr< const PixelDiodeMatrix > m_middleCells
std::string createDebugStringRepr() const
Create debug representation.
PixelDiodeMatrix()
Hidden constructor.
bool singleCell() const
Query wether the matrix is just a single cell.
void initialize(double phiWidth, double etaWidth)
Initialize for just a single cell.
static std::shared_ptr< const PixelDiodeMatrix > construct(double phiWidth, double etaWidth)
Construct method for just a single cell.
int phiCells() const
Number of cells in phi (x) direction.
int etaCells() const
Number of cells in eta (y) direction.
const PixelDiodeMatrix * positionOfCell(const SiCellId &cellId, Amg::Vector2D &position) const
Search diode matching the given cell id and compute its position.
double etaWidth() const
Width in eta (y) direction.
double phiWidth() const
Width in phi (x) direction.
std::shared_ptr< const PixelDiodeMatrix > m_lowerCell
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
int phiIndex() const
Get phi index. Equivalent to strip().
Definition SiCellId.h:122
int etaIndex() const
Get eta index.
Definition SiCellId.h:114
Eigen::Matrix< double, 2, 1 > Vector2D
Message Stream Member.
@ distEta
readout for silicon
Definition ParamDefs.h:51
@ distPhi
Definition ParamDefs.h:50
@ distEta
readout for silicon
Definition ParamDefs.h:51
@ distPhi
Definition ParamDefs.h:50
Definition index.py:1