ATLAS Offline Software
Loading...
Searching...
No Matches
NNPixelClusterCalibratorHelpers.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4#ifndef NNPIXELCLUSTERCALIBRATORHELPERS_H
5#define NNPIXELCLUSTERCALIBRATORHELPERS_H
6
7#include <algorithm>
8#include <array>
9#include <cmath>
10#include <cstddef>
11#include <numeric>
12#include <span>
13#include <stdexcept>
14#include <vector>
15
18
19namespace ActsTrk {
20class NNinput {
21 public:
22 using payload_t = float;
23 using index_t = int;
38 NNinput() : m_payload(static_cast<index_t>(Index::totalSize), {}) {}
39
40 std::vector<payload_t>& payload() { return m_payload; }
41
42 const std::vector<payload_t>& payload() const { return m_payload; }
43
44 float totCharge() const {
45 return std::accumulate(
46 std::begin(m_payload) + static_cast<index_t>(Index::chargeOffset),
47 std::begin(m_payload) + static_cast<index_t>(Index::chargeEnd), 0.0f);
48 }
49
51 checkRange(x, "x of coordinate of the charge");
52 checkRange(y, "x of coordinate of the charge");
53
54 m_payload[static_cast<index_t>(Index::chargeOffset) +
55 x * static_cast<index_t>(Index::windowSize) + y] = charge;
56 }
57
59 checkRange(i, "x pitch");
60 m_payload[static_cast<index_t>(Index::pitchXOffset) + i] = pitch;
61 }
62
64 return m_payload[static_cast<index_t>(Index::pitchXOffset) + i];
65 }
66
68 checkRange(i, "y pitch");
69 m_payload[static_cast<index_t>(Index::pitchYOffset) + i] = pitch;
70 }
71
72 void set(Index i, payload_t v) { m_payload[static_cast<index_t>(i)] = v; }
73
76 // they will become 2 3 4
80 static int toNNinputIndex(index_t pixelIndex, index_t centerIndex) {
81 return pixelIndex - centerIndex +
82 static_cast<NNinput::index_t>(Index::center);
83 }
84
88 static int toModuleIndex(index_t nnIndex, index_t centerIndex) {
89 return nnIndex + centerIndex - static_cast<NNinput::index_t>(Index::center);
90 }
91
92 static bool inWindow(index_t x, index_t y) {
93 return x >= 0 && x < static_cast<index_t>(Index::windowSize) && y >= 0 &&
94 y < static_cast<index_t>(Index::windowSize);
95 }
96
108 float indexCoordToRealCoord(float coord, Index pitchOffset) {
109 std::span<payload_t, static_cast<index_t>(Index::windowSize)> pitches(
110 m_payload.begin() + static_cast<index_t>(pitchOffset),
111 m_payload.begin() + static_cast<index_t>(pitchOffset) +
112 static_cast<index_t>(Index::windowSize));
113 const std::size_t windowSize = static_cast<std::size_t>(Index::windowSize);
114
115 std::array<double, static_cast<std::size_t>(Index::windowSize)>
116 cumulative{};
117 double acc = 0.0;
118 for (std::size_t j = 0; j < windowSize; ++j) {
119 acc += pitches[j];
120 cumulative[j] = acc;
121 }
122
123 const std::size_t centerIdx = static_cast<std::size_t>(Index::center);
124 const double centerValue = cumulative[centerIdx];
125 for (double& value : cumulative) {
126 value -= centerValue;
127 }
128
129 const double coordsIdx = coord + static_cast<double>(Index::center);
130 const double floorValue = std::floor(coordsIdx);
131 const double frac = floorValue - coordsIdx;
132 const long intIdx = static_cast<long>(floorValue);
133 const long clippedIdx = std::clamp(intIdx, static_cast<long>(0),
134 static_cast<long>(windowSize) - 1);
135 const double base = cumulative[clippedIdx];
136 const double pitchAtIdx = pitches[clippedIdx];
137 const double centerOfCluster = pitchOffset == Index::pitchXOffset
138 ? this->centerPosition.xPhi()
139 : this->centerPosition.xEta();
140 return base + std::abs(frac) * pitchAtIdx + centerOfCluster;
141 }
142
151 float precisionToRealCoord(float prec, Index pitchOffset) {
152 std::span<payload_t, static_cast<index_t>(Index::windowSize)> pitches(
153 m_payload.begin() + static_cast<index_t>(pitchOffset),
154 m_payload.begin() + static_cast<index_t>(pitchOffset) +
155 static_cast<index_t>(Index::windowSize));
156
157 const float p = ((prec > 0) ? std::sqrt(1.0f / prec) : 0.01f) +
158 static_cast<float>(Index::center);
159 float pitchPos = -100; // unset position
160 float pitchCenter = -100; // unset position
161 float pitchActual = 0; // integral of pitch sizes
162 for (index_t i = 0; i < static_cast<index_t>(Index::windowSize); i++) {
163 if (p >= i and p <= (i + 1))
164 pitchPos = pitchActual + (p - i + 0.5) * pitches[i];
165 if (i == static_cast<index_t>(Index::center))
166 pitchCenter = pitchActual + 0.5 * pitches[i];
167 pitchActual += pitches[i];
168 }
169 return std::abs(pitchPos - pitchCenter);
170 }
171
176
177 private:
178 std::vector<payload_t> m_payload;
179
181 void checkRange(index_t i, const std::string& context) const {
182 if (i >= static_cast<index_t>(Index::windowSize))
183 throw std::domain_error(
184 "Filling the NNinput for pixel calibration, the value should be "
185 "within 0-6, while it "
186 "is " +
187 std::to_string(i) + " " + context);
188 }
189};
190
193
194 /***
195 * @brief given number network output finds how many clusters there is
196 * the numbers network resurns probabilities and we decide picking
197 * highest probability outcome (position of highest probability +1 == nnumber
198 * of clusters)
199 * TODO check if in case of small differences in prob, we should not preffer
200 * smaller number of clusters
201 */
202 static unsigned int maxProbIndex(const std::array<payload_t, 3>& prob) {
203 return std::ranges::distance(std::begin(prob),
204 std::ranges::max_element(prob));
205 }
206};
207
208/***
209 * @brief helper for decoding position networks output
210 * Each position set contains 4 numbers x,y, and precision
211 * Clusters are counted from 0,1,2 (max)
212 * Data encoded according to:
213 * https://pixsplit.docs.cern.ch/architecture/#positionregressor
214 */
216 public:
226
227 PositionNNoutput(const float* begin, const float* end)
228 : m_payload(begin, end) {}
230 : m_payload(nPos = static_cast<index_t>(Index::outputUnitSize)) {}
231
232 std::vector<payload_t>& payload() { return m_payload; }
233
237 return m_payload.size() / static_cast<index_t>(Index::outputUnitSize);
238 }
239
243 payload_t x(index_t cluster) {
244 return m_payload[cluster * static_cast<index_t>(Index::outputUnitSize) +
245 static_cast<index_t>(Index::xOffset)];
246 }
247
249 payload_t y(index_t cluster) {
250 return m_payload[cluster * static_cast<index_t>(Index::outputUnitSize) +
251 static_cast<index_t>(Index::yOffset)];
252 }
253
256 return m_payload[cluster * static_cast<index_t>(Index::outputUnitSize) +
257 static_cast<index_t>(Index::xPrecOffset)];
258 }
259
261 return m_payload[cluster * static_cast<index_t>(Index::outputUnitSize) +
262 static_cast<index_t>(Index::yPrecOffset)];
263 }
264
265 private:
266 std::vector<payload_t> m_payload;
267};
268
269} // namespace ActsTrk
270
271#endif
Scalar phi() const
phi method
Scalar theta() const
theta method
double charge(const T &p)
Definition AtlasPID.h:997
double coord
Type of coordination system.
static unsigned int totalSize(const MultiDimArray< T, N > &ht)
#define y
#define x
float precisionToRealCoord(float prec, Index pitchOffset)
translate RMS that is output from NN to detector units (mm) Conversion is done by integrating the act...
const std::vector< payload_t > & payload() const
void setPixelYPitch(index_t i, payload_t pitch)
static int toModuleIndex(index_t nnIndex, index_t centerIndex)
Reverse operation to toNNInputIndex.
void set(Index i, payload_t v)
payload_t getPixelXPitch(index_t i) const
void checkRange(index_t i, const std::string &context) const
! storage for NN input
float indexCoordToRealCoord(float coord, Index pitchOffset)
translates position returned from the network to mm The position returned from the network is given i...
static bool inWindow(index_t x, index_t y)
InDetDD::SiLocalPosition centerPosition
void setPixelCharge(index_t x, index_t y, payload_t charge)
std::vector< payload_t > & payload()
static int toNNinputIndex(index_t pixelIndex, index_t centerIndex)
Translate from module indices to NNinput indices e.g.
void setPixelXPitch(index_t i, payload_t pitch)
std::vector< payload_t > m_payload
PositionNNoutput(const float *begin, const float *end)
index_t numberOfSubClusters()
returns number of (sub)clusters Effectively it depends on the position network used
payload_t xprec(index_t cluster)
precision in nn coordinates
payload_t x(index_t cluster)
x position (in nn coordinates)
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
Class to represent a position in the natural frame of a silicon sensor, for Pixel and SCT For Pixel: ...
std::string base
Definition hcg.cxx:83
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
static unsigned int maxProbIndex(const std::array< payload_t, 3 > &prob)
! payload from NN