ATLAS Offline Software
Loading...
Searching...
No Matches
PixelDiodeTree.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
5#include <sstream>
6#include <iomanip>
7#include <utility>
8
9namespace InDetDD {
10
12 unsigned int errors=0;
13 constexpr std::array<IndexType,2> axis_offset{1,2};
14 for (std::array<IndexType,4> &a_split : m_subMatrixIndex) {
15 unsigned int n_invalid=0;
16 IndexType good_idx=s_invalid;
17 std::array<std::array<unsigned int,2>,2> n_invalid_halves{};
18 for (unsigned int element_i=0; element_i<a_split.size(); ++element_i) {
19 bool is_invalid = a_split.at(element_i)==s_invalid;
20 unsigned int axis0=element_i/2;
21 unsigned int axis1=element_i%2;
22 n_invalid_halves[0][axis0]+=is_invalid;
23 n_invalid_halves[1][axis1]+=is_invalid;
24 if (is_invalid) ++n_invalid;
25 else { good_idx=a_split[element_i]; }
26 }
27 if (n_invalid==3) {
28 assert( good_idx != s_invalid);
29 for (unsigned int element_i=0; element_i<a_split.size(); ++element_i) {
30 a_split.at(element_i)=good_idx;
31 }
32 }
33 else if (n_invalid==2) {
34 unsigned int element_i=std::numeric_limits<unsigned int>::max();
35 for (unsigned int axis_i=0; axis_i<2; ++axis_i) {
36 for (unsigned int side_i=0; side_i<2; ++side_i) {
37 if (n_invalid_halves[axis_i][side_i]==2 && n_invalid_halves[axis_i][side_i^1]==0) {
38 element_i=axis_offset[axis_i^1]*side_i;
39 IndexType other_element_i = axis_offset[axis_i^1]*(side_i==1 ? -1 : 1);
40 unsigned int element_end_i=element_i+axis_offset[axis_i]*2;
41 for(; element_i<element_end_i; element_i+=axis_offset[axis_i] ) {
42 a_split[ element_i ] = a_split[ element_i + other_element_i] ;
43 }
44 break;
45 }
46 if (element_i != std::numeric_limits<unsigned int>::max()) break;
47 }
48 }
49 if (element_i == std::numeric_limits<unsigned int>::max()) {
50 errors += 2;
51 }
52 }
53 else if (n_invalid!=0) {
54 errors +=2;
55 }
56 }
57
58 return errors;
59}
60
61void PixelDiodeTree::computeMatrixCorner(const std::array<PixelDiodeTree::CellIndexType,2> &matrix_dim) {
62 assert( matrix_dim[0]>0 && matrix_dim[1]>0);
63 m_matrixDim=matrix_dim;
65 {
66 DiodeProxyWithPosition lower_corner_proxy(diodeProxyFromIdxCachePosition(std::array<CellIndexType,2> {}));
67 m_matrixCorner[0]=lower_corner_proxy.position() - lower_corner_proxy.width()*.5;
68 for (unsigned int axis_i=0; axis_i<2; ++axis_i) {
69 m_matrixCorner[0][axis_i] += tolerance[axis_i];
70 }
71 }
72
73 {
74 DiodeProxyWithPosition upper_corner_proxy(diodeProxyFromIdxCachePosition(std::array<PixelDiodeTree::CellIndexType,2> {matrix_dim[0]-1,
75 matrix_dim[1]-1}));
76 m_matrixCorner[1]=upper_corner_proxy.position() + upper_corner_proxy.width()*.5 ;
77 for (unsigned int axis_i=0; axis_i<2; ++axis_i) {
78 m_matrixCorner[1][axis_i] -= tolerance[axis_i];
79 }
80 }
82 throw std::logic_error("Logic error! Matrix corner positions do not yield valid indices for this matrix!");
83 }
84}
85
86PixelDiodeTree::Vector2D PixelDiodeTree::computeTolerance(const std::array<PixelDiodeTree::CellIndexType,2> &matrix_dim) const {
88 for (unsigned int axis_i=0; axis_i<2; ++axis_i) {
89 assert( matrix_dim[axis_i]>0 &&
90 static_cast<unsigned int>(std::abs(matrix_dim[axis_i])) < std::numeric_limits<unsigned int>::max());
91 unsigned int bits_i=0;
92 for (; bits_i<16 && 1u<<bits_i < static_cast<unsigned int>(matrix_dim[axis_i])*3; ++bits_i);
93 tolerance[axis_i]=(1u<<bits_i) * std::numeric_limits<PixelDiodeTree::FloatType>::epsilon();
94 }
95 return tolerance;
96}
97
99 std::stringstream out;
100 if (!m_diodeParam.m_width.empty()) {
101 if ( m_idxSplit.size() != m_posSplit.size()
102 || m_idxSplit.size() != m_subMatrixIndex.size()
103 || m_idxSplit.size() != m_attribute.size()
104 || m_diodeParam.m_width.size() != m_diodeParam.m_invWidth.size()
105 || m_diodeParam.m_width.size() != m_diodeParam.m_attribute.size()) {
106 // should never happer
107 out << "PixelDiodeTree is inconsistent. Expected identical number of elements but has the following "
108 << " container sizes: index-split points : " << m_idxSplit.size()
109 << " position split points : " << m_posSplit.size()
110 << " submatrices : " << m_subMatrixIndex.size()
111 << " attributes : " << m_attribute.size()
112 << "; diodes : width : " << m_diodeParam.m_width.size()
113 << " inverted width : " << m_diodeParam.m_invWidth.size()
114 << " attributes : " << m_diodeParam.m_attribute.size()
115 << ".\n";
116 }
117 else {
118 out << "PixelDiodeTree total width : " << m_diodeParam.m_width[0][0] << "x" << m_diodeParam.m_width[0][1] << " mm^2" << "\n:";
119 std::vector<std::pair<IndexType,unsigned int> > submatrix_stack;
120 submatrix_stack.push_back(std::make_pair(0u,2u));
121 while (!submatrix_stack.empty()) {
122 auto [submatrix_idx, margin] = submatrix_stack.back();
123 submatrix_stack.pop_back();
124 out << std::setw(margin) << ' ';
125 if (submatrix_idx < 0) {
126 if (submatrix_idx!=s_invalid) {
127 unsigned int diode_idx=std::abs(submatrix_idx);
128 if (diode_idx<m_diodeParam.m_width.size()) {
129 out << " diode width " << m_diodeParam.m_width[diode_idx][0] << " x " << m_diodeParam.m_width[diode_idx][1]
130 << " attribute " << std::hex << m_diodeParam.m_attribute[diode_idx] << std::dec << "\n";
131 }
132 }
133 }
134 else if (static_cast<std::size_t>(submatrix_idx) >= m_idxSplit.size()) {
135 out << "Invalid sub-matrix index : " << submatrix_idx << "\n";
136 }
137 else {
138 out << " split at (row,col) " << m_idxSplit[submatrix_idx][0] << " " << m_idxSplit[submatrix_idx][1]
139 << " , position (local-x/-y) " << m_posSplit[submatrix_idx][0] << " " << m_posSplit[submatrix_idx][1]
140 << " attribute " << std::hex << m_attribute[submatrix_idx] << std::dec
141 << " sub-matrices (diodes): ";
142 for (unsigned int split_i=0; split_i<m_subMatrixIndex[submatrix_idx].size(); ++split_i) {
143 out << (split_i==2 ? " | " : " ");
144 if (m_subMatrixIndex[submatrix_idx][split_i] == s_invalid) {
145 out << "-";
146 }
147 else {
148 out << m_subMatrixIndex[submatrix_idx][split_i];
149 }
150 }
151 out << "\n";
152 for (std::array<IndexType,4>::const_reverse_iterator iter = m_subMatrixIndex[submatrix_idx].rbegin();
153 iter != m_subMatrixIndex[submatrix_idx].rend();
154 ++iter) {
155 if (*iter != s_invalid) {
156 submatrix_stack.push_back( std::make_pair( *iter, margin+2));
157 }
158 }
159 }
160 }
161 }
162 }
163 else {
164 out << "PixelDiodeTree with " << m_subMatrixIndex.size() << " has no diodes." << "\n";
165 }
166 return out.str();
167}
168}
bool isInsideMatrix(const std::array< PixelDiodeTree::IndexType, 2 > &idx) const
Return true if the given index describes a valid location inside the matrix.
std::array< CellIndexType, 2 > m_matrixDim
std::array< CellIndexType, 2 > findFromPos(const Vector2D &pos) const
Find a diode by the position relative to the center of the full diode matrix and compute its 2D index...
static constexpr IndexType s_invalid
std::vector< std::array< IndexType, 4 > > m_subMatrixIndex
std::array< Vector2D, 2 > m_matrixCorner
PixelDiodeTree::Vector2D computeTolerance(const std::array< PixelDiodeTree::CellIndexType, 2 > &matrix_dim) const
Compute tolerance to ensure that a position is within the expected cell Due to limited floating point...
unsigned int cloneSingleSplitsToUnusedHalf()
Clone half with valid split indices to "unused" half with invalid split indices.
std::vector< AttributeType > m_attribute
std::vector< Vector2D > m_posSplit
std::vector< std::array< CellIndexType, 2 > > m_idxSplit
std::string debugStringRepr() const
Dump the diode tree structure into a string.
void computeMatrixCorner(const std::array< PixelDiodeTree::CellIndexType, 2 > &matrix_dim)
Compute the effective maximum lower and upper corner positions of the matrix.
DiodeProxyWithPosition diodeProxyFromIdxCachePosition(const std::array< CellIndexType, 2 > &idx) const
find a diode by its 2D index (row, column) and compute the position of the diode the returned proxy c...
Message Stream Member.
A diode proxy which caches the position of a diode.