Check vector sizes and reciprocal cross-block indices.
25 {
26 const std::size_t nTruth = event.truth.pdgId.size();
27 const std::size_t nSegments = event.segments.subdetectorId.size();
28 const std::size_t nCandidates = event.candidates.subdetectorId.size();
29
30 const auto invalid = [](std::string message) {
32 };
33 const auto checkTruthSize = [&](
const std::size_t
size,
37 : invalid(std::string{"Truth block size mismatch for "} +
39 };
40 const auto checkSegmentSize = [&](
const std::size_t
size,
42 return size == nSegments
44 : invalid(std::string{"Segment block size mismatch for "} +
46 };
47 const auto checkCandidateSize = [&](
const std::size_t
size,
49 return size == nCandidates
51 : invalid(std::string{"Candidate block size mismatch for "} +
53 };
54
55#define TGC_CHECK_TRUTH_SIZE(FIELD) \
56 do { \
57 const auto result = checkTruthSize( \
58 event.truth.FIELD.size(), #FIELD); \
59 if (!result.valid) return result; \
60 } while (false)
61
84#undef TGC_CHECK_TRUTH_SIZE
85
86#define TGC_CHECK_SEGMENT_SIZE(FIELD) \
87 do { \
88 const auto result = checkSegmentSize( \
89 event.segments.FIELD.size(), #FIELD); \
90 if (!result.valid) return result; \
91 } while (false)
92
107#undef TGC_CHECK_SEGMENT_SIZE
108
109#define TGC_CHECK_CANDIDATE_SIZE(FIELD) \
110 do { \
111 const auto result = checkCandidateSize( \
112 event.candidates.FIELD.size(), #FIELD); \
113 if (!result.valid) return result; \
114 } while (false)
115
130#undef TGC_CHECK_CANDIDATE_SIZE
131
132 const auto wireProjection =
134 const auto stripProjection =
136
137 for (std::size_t segment = 0U; segment < nSegments; ++segment) {
138 const std::uint8_t projection = event.segments.projection[segment];
139 if (projection != wireProjection && projection != stripProjection) {
140 return invalid("Segment projection is not wire or strip");
141 }
142 if (
event.segments.nStations[segment] == 0U ||
143 event.segments.nStations[segment] > 3U) {
144 return invalid("Segment station count is out of range");
145 }
146 const int truth = event.segments.truthIndex[segment];
147 if (truth >= 0 && static_cast<std::size_t>(truth) >= nTruth) {
148 return invalid("Segment truth index is out of range");
149 }
150 const float residual =
event.segments.truthMatchResidual[segment];
151 if (truth >= 0 &&
152 (!std::isfinite(residual) ||
154 return invalid("Matched segment has an invalid truth residual");
155 }
157 return invalid("Unmatched segment has a truth residual");
158 }
159 }
160
161 for (
const int truth :
event.candidates.truthIndex) {
162 if (truth >= 0 && static_cast<std::size_t>(truth) >= nTruth) {
163 return invalid("Candidate truth index is out of range");
164 }
165 }
166
167 std::vector<int> candidateOwner(nCandidates, -1);
168 for (std::size_t truth = 0U; truth < nTruth; ++truth) {
169 if (
event.truth.matched[truth] > 1U) {
170 return invalid("Truth matched flag is not binary");
171 }
172 const bool matched = event.truth.matched[truth] != 0U;
173 const int candidate = event.truth.matchedCandidateIndex[truth];
174 if (candidate >= 0 && static_cast<std::size_t>(candidate) >= nCandidates) {
175 return invalid("Truth matched-candidate index is out of range");
176 }
177 if (matched && candidate < 0) {
178 return invalid("Matched truth has no candidate index");
179 }
180 if (!matched && candidate >= 0) {
181 return invalid("Unmatched truth has a candidate index");
182 }
183 if (matched &&
184 event.truth.unmatchedReason[truth] !=
186 return invalid("Matched truth has an unmatched-reason code");
187 }
188 if (!matched &&
189 event.truth.unmatchedReason[truth] ==
191 return invalid("Unmatched truth has no unmatched-reason code");
192 }
193 if (!matched &&
194 event.truth.unmatchedReason[truth] >
195 static_cast<std::uint8_t>(
197 return invalid("Truth unmatched-reason code is out of range");
198 }
199 if (matched &&
200 (!std::isfinite(
event.truth.matchMeanDeltaR[truth]) ||
202 return invalid("Matched truth has an invalid candidate residual");
203 }
204 if (!matched &&
206 return invalid("Unmatched truth has a candidate residual");
207 }
208 if (candidate >= 0) {
209 const auto candidateIndex = static_cast<std::size_t>(candidate);
210 if (candidateOwner[candidateIndex] >= 0) {
211 return invalid("Candidate is matched to more than one truth muon");
212 }
213 candidateOwner[candidateIndex] = static_cast<int>(truth);
214 if (
event.candidates.truthIndex[candidateIndex] !=
215 static_cast<int>(truth)) {
216 return invalid("Truth-candidate matching indices are not reciprocal");
217 }
218 }
219
220 if (
event.truth.wireSegmentMatched[truth] > 1U ||
221 event.truth.stripSegmentMatched[truth] > 1U) {
222 return invalid("Truth segment-matched flag is not binary");
223 }
224 const bool wireMatched = event.truth.wireSegmentMatched[truth] != 0U;
225 const bool stripMatched = event.truth.stripSegmentMatched[truth] != 0U;
226 const int wireSegment = event.truth.matchedWireSegmentIndex[truth];
227 const int stripSegment = event.truth.matchedStripSegmentIndex[truth];
228 if (wireSegment >= 0 &&
229 static_cast<std::size_t>(wireSegment) >= nSegments) {
230 return invalid("Truth matched-wire-segment index is out of range");
231 }
232 if (stripSegment >= 0 &&
233 static_cast<std::size_t>(stripSegment) >= nSegments) {
234 return invalid("Truth matched-strip-segment index is out of range");
235 }
236 if (wireMatched && wireSegment < 0) {
237 return invalid("Wire-segment-matched truth has no segment index");
238 }
239 if (stripMatched && stripSegment < 0) {
240 return invalid("Strip-segment-matched truth has no segment index");
241 }
242 if (!wireMatched && wireSegment >= 0) {
243 return invalid("Wire-segment-unmatched truth has a segment index");
244 }
245 if (!stripMatched && stripSegment >= 0) {
246 return invalid("Strip-segment-unmatched truth has a segment index");
247 }
248 if (wireMatched &&
249 (!std::isfinite(
event.truth.wireSegmentMatchResidual[truth]) ||
250 event.truth.wireSegmentMatchResidual[truth] ==
252 return invalid("Wire-segment-matched truth has an invalid residual");
253 }
254 if (!wireMatched &&
255 event.truth.wireSegmentMatchResidual[truth] !=
257 return invalid("Wire-segment-unmatched truth has a residual");
258 }
259 if (stripMatched &&
260 (!std::isfinite(
event.truth.stripSegmentMatchResidual[truth]) ||
261 event.truth.stripSegmentMatchResidual[truth] ==
263 return invalid("Strip-segment-matched truth has an invalid residual");
264 }
265 if (!stripMatched &&
266 event.truth.stripSegmentMatchResidual[truth] !=
268 return invalid("Strip-segment-unmatched truth has a residual");
269 }
270 if (wireSegment >= 0 &&
271 event.segments.projection[wireSegment] != wireProjection) {
272 return invalid("Truth wire-segment index points to a strip segment");
273 }
274 if (stripSegment >= 0 &&
275 event.segments.projection[stripSegment] != stripProjection) {
276 return invalid("Truth strip-segment index points to a wire segment");
277 }
278 if ((wireSegment >= 0 &&
279 event.segments.truthIndex[wireSegment] !=
static_cast<int>(truth)) ||
280 (stripSegment >= 0 &&
281 event.segments.truthIndex[stripSegment] !=
static_cast<int>(truth))) {
282 return invalid("Truth-segment matching indices are not reciprocal");
283 }
284 }
285
286 for (std::size_t candidate = 0U; candidate < nCandidates; ++candidate) {
287 const int truth = event.candidates.truthIndex[candidate];
288 if (truth < 0) continue;
289 if (
event.truth.matched[truth] == 0U ||
290 event.truth.matchedCandidateIndex[truth] !=
291 static_cast<int>(candidate)) {
292 return invalid("Truth-candidate matching indices are not reciprocal");
293 }
294 }
295
296 for (std::size_t segment = 0U; segment < nSegments; ++segment) {
297 const int truth = event.segments.truthIndex[segment];
298 if (truth < 0) continue;
299 const bool isWire = event.segments.projection[segment] == wireProjection;
300 const int reverseIndex =
301 isWire ? event.truth.matchedWireSegmentIndex[truth]
302 : event.truth.matchedStripSegmentIndex[truth];
303 if (reverseIndex != static_cast<int>(segment)) {
304 return invalid("Truth-segment matching indices are not reciprocal");
305 }
306 }
307
308 return {};
309}
Scalar eta() const
pseudorapidity method
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
Scalar phi() const
phi method
double charge(const T &p)
size_t size() const
Number of registered mappings.
unsigned bcTag(unsigned bcBitMap)
#define TGC_CHECK_SEGMENT_SIZE(FIELD)
#define TGC_CHECK_TRUTH_SIZE(FIELD)
#define TGC_CHECK_CANDIDATE_SIZE(FIELD)
static constexpr float TgcL0ValidationInvalidValue
Common sentinel for unavailable floating-point validation data.
static constexpr std::uint8_t TgcL0ValidationNoUnmatchedReason
Sentinel indicating that a matched truth object has no failure code.
Result of a structural validation-data consistency check.