Project
Loading...
Searching...
No Matches
UserLogicChecker.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
18
19#include <sstream>
20#include <fmt/format.h>
21
22namespace o2
23{
24namespace mid
25{
26
27bool UserLogicChecker::isSame(const o2::mid::ROBoard& loc1, const o2::mid::ROBoard& loc2) const
28{
30 if (loc1.statusWord == loc2.statusWord && loc1.triggerWord == loc2.triggerWord && loc1.firedChambers == loc2.firedChambers && loc1.boardId == loc2.boardId) {
31 for (int ich = 0; ich < 4; ++ich) {
32 if (loc1.patternsBP[ich] != loc2.patternsBP[ich] || loc1.patternsNBP[ich] != loc2.patternsNBP[ich]) {
33 return false;
34 }
35 }
36 return true;
37 }
38 return false;
39}
40
41std::string UserLogicChecker::printIRHex(const o2::InteractionRecord& ir) const
42{
44 return fmt::format("BCid: 0x{:x} Orbit: 0x{:x}", ir.bc, ir.orbit);
45}
46
47uint32_t UserLogicChecker::getId(const ROBoard& board) const
48{
50 uint32_t id = static_cast<uint32_t>(board.boardId);
51 if (!raw::isLoc(board.statusWord)) {
52 id |= (1 << 16);
53 }
54 return id;
55}
56
57void UserLogicChecker::fillBoards(gsl::span<const ROBoard> data, gsl::span<const ROFRecord> rofRecords, bool isUL)
58{
60
61 auto& boards = isUL ? mBoardsUL : mBoardsBare;
62
63 // The UL rejects the events outside the SOX/EOX
64 // So we should do the same
65 for (auto rofIt = rofRecords.begin(); rofIt != rofRecords.end(); ++rofIt) {
66 auto& loc = data[rofIt->firstEntry];
67 auto id = getId(loc);
68 auto isInside = mInsideDataTaking.find(id);
69 if (isInside == mInsideDataTaking.end()) {
70 mInsideDataTaking[id] = false;
71 isInside = mInsideDataTaking.find(id);
72 }
73 if (loc.triggerWord & raw::sSOX) {
74 isInside->second = true;
75 } else if (loc.triggerWord & raw::sEOX) {
76 isInside->second = false;
77 }
78 if (loc.triggerWord & raw::sPHY) {
79 continue; // Skip physics triggers since they are not present in UL
80 }
81 if (isInside->second) {
82 boards[id].push_back({rofIt->interactionRecord, loc});
83 }
84 }
85}
86
87void UserLogicChecker::clearBoards()
88{
90
91 for (int itype = 0; itype < 2; ++itype) {
92 auto& boards = (itype == 0) ? mBoardsUL : mBoardsBare;
93 auto& lastChecked = (itype == 0) ? mLastCheckedUL : mLastCheckedBare;
94 std::unordered_map<uint32_t, std::vector<boardInfo>> newBoards;
95 for (auto& boardItem : boards) {
96 auto lastIdxItem = lastChecked.find(boardItem.first);
97 if (lastIdxItem->second != boardItem.second.size()) {
98 auto& vec = newBoards[boardItem.first];
99 vec.insert(vec.end(), boardItem.second.begin() + lastIdxItem->second, boardItem.second.end());
100 }
101 }
102 boards.swap(newBoards);
103 lastChecked.clear();
104 }
105}
106
107bool UserLogicChecker::checkBoards(gsl::span<const ROBoard> bareData, gsl::span<const ROFRecord> bareRofs, gsl::span<const ROBoard> ulData, gsl::span<const ROFRecord> ulRofs)
108{
110 clearBoards();
111 fillBoards(bareData, bareRofs, false);
112 fillBoards(ulData, ulRofs, true);
113 bool isOk = true;
114
115 for (auto& bareItem : mBoardsBare) {
116 std::string boardType = (bareItem.first < 0x10000) ? "Loc" : "Reg";
117 auto& lastCheckedBare = mLastCheckedBare[bareItem.first];
118 auto& stats = mStatistics[bareItem.first];
119 stats[0] += bareItem.second.size();
120 std::stringstream ss;
121 ss << "\n-----------" << std::endl;
122 uint16_t boardId = (bareItem.first & 0xFFFF);
123 ss << "Checking crate: " << static_cast<int>(raw::getCrateId(boardId))
124 << " " << boardType << " board: " << static_cast<int>(raw::getLocId(boardId)) << std::endl;
125 auto ulItem = mBoardsUL.find(bareItem.first);
126 if (ulItem == mBoardsUL.end()) {
127 ss << " cannot find " << printIRHex(bareItem.second.front().interactionRecord) << " in ul" << std::endl;
128 isOk = false;
129 ss << "-----------" << std::endl;
130 mDebugMsg += ss.str();
131 stats[1] += bareItem.second.size();
132 continue;
133 }
134 auto& lastCheckedUL = mLastCheckedUL[ulItem->first];
135 lastCheckedUL = 0;
136 auto lastOk = lastCheckedUL;
137 bool isCurrentOk = true;
138 for (lastCheckedBare = 0; lastCheckedBare < bareItem.second.size(); ++lastCheckedBare) {
139 if (lastCheckedUL == ulItem->second.size()) {
140 break;
141 } else if (!isSame(ulItem->second[lastCheckedUL].board, bareItem.second[lastCheckedBare].board) || ulItem->second[lastCheckedUL].interactionRecord != bareItem.second[lastCheckedBare].interactionRecord) {
142 ss << "\nFirst divergence at element " << lastCheckedBare + 1 << " / " << bareItem.second.size() << ":" << std::endl;
143 ss << "bare: " << printIRHex(bareItem.second[lastCheckedBare].interactionRecord) << std::endl;
144 ss << bareItem.second[lastCheckedBare].board << std::endl;
145 ss << "ul: " << printIRHex(ulItem->second[lastCheckedUL].interactionRecord) << std::endl;
146 ss << ulItem->second[lastCheckedUL].board << std::endl;
147 isCurrentOk = false;
148 }
149 if (!isCurrentOk) {
150 if (lastOk != lastCheckedUL) {
151 ss << "lastOk: " << printIRHex(ulItem->second[lastOk].interactionRecord) << std::endl;
152 ss << ulItem->second[lastOk].board << std::endl;
153 } else {
154 ss << "lastOk: none. This is the first event!" << std::endl;
155 }
156 ss << "-----------" << std::endl;
157 mDebugMsg += ss.str();
158 stats[1] += lastCheckedUL;
159 lastCheckedUL = ulItem->second.size();
160 lastCheckedBare = bareItem.second.size();
161 isOk = false;
162 break;
163 }
164 lastOk = lastCheckedUL;
165 ++lastCheckedUL;
166 } // loop on bare data for this board ID
167 } // loop on board IDs
168 return isOk;
169}
170
171std::unordered_map<uint64_t, std::vector<size_t>> UserLogicChecker::getOrderedIndexes(gsl::span<const ROFRecord> rofRecords) const
172{
173 // Orders data according to their IR
174 std::unordered_map<uint64_t, std::vector<size_t>> orderIndexes;
175 for (auto rofIt = rofRecords.begin(); rofIt != rofRecords.end(); ++rofIt) {
176 // Fill the map with ordered events
177 orderIndexes[rofIt->interactionRecord.toLong()].emplace_back(rofIt->firstEntry);
178 }
179 return orderIndexes;
180}
181
182bool UserLogicChecker::checkAll(gsl::span<const ROBoard> bareData, gsl::span<const ROFRecord> bareRofs, gsl::span<const ROBoard> ulData, gsl::span<const ROFRecord> ulRofs)
183{
184 auto bareIndexes = getOrderedIndexes(bareRofs);
185 auto ulIndexes = getOrderedIndexes(ulRofs);
186
187 bool isOk = true;
188 std::stringstream ss;
189 InteractionRecord ir;
190 for (auto& bareItem : bareIndexes) {
191 auto ulItem = ulIndexes.find(bareItem.first);
192 ir.setFromLong(bareItem.first);
193 if (ulItem == ulIndexes.end()) {
194 isOk = false;
195 ss << "\nCannot find: " << printIRHex(ir) << " in ul\n";
196 continue;
197 }
198 std::vector<size_t> auxVec = ulItem->second;
199 for (auto& idx1 : bareItem.second) {
200 bool found = false;
201 for (auto auxIt = auxVec.begin(); auxIt != auxVec.end(); ++auxIt) {
202 if (isSame(bareData[idx1], ulData[*auxIt])) {
203 auxVec.erase(auxIt);
204 found = true;
205 break;
206 }
207 }
208 if (!found) {
209 isOk = false;
210 ss << "\nOnly in bare: " << printIRHex(ir) << "\n";
211 ss << " " << bareData[idx1] << "\n";
212 }
213 }
214 for (auto& idx2 : auxVec) {
215 isOk = false;
216 ss << "\nOnly in ul: " << printIRHex(ir) << "\n";
217 ss << " " << ulData[idx2] << "\n";
218 }
219 }
220
221 for (auto& ulItem : ulIndexes) {
222 auto bareItem = bareIndexes.find(ulItem.first);
223 if (bareItem == bareIndexes.end()) {
224 isOk = false;
225 ir.setFromLong(ulItem.first);
226 ss << "\nCannot find: " << printIRHex(ir) << " in bare\n";
227 }
228 }
229 mDebugMsg = ss.str();
230 return isOk;
231}
232
233bool UserLogicChecker::process(gsl::span<const ROBoard> bareData, gsl::span<const ROFRecord> bareRofs, gsl::span<const ROBoard> ulData, gsl::span<const ROFRecord> ulRofs, bool isFull)
234{
236 mDebugMsg.clear();
237 return isFull ? checkAll(bareData, bareRofs, ulData, ulRofs) : checkBoards(bareData, bareRofs, ulData, ulRofs);
238}
239
241{
243 mInsideDataTaking.clear();
244 mStatistics.clear();
245}
246
248{
250 std::stringstream ss;
251 for (auto& statItem : mStatistics) {
252 std::string boardType = (statItem.first < 0x10000) ? "Loc" : "Reg";
253 double badFraction = (statItem.second[0] == 0) ? 0. : static_cast<double>(statItem.second[1]) / static_cast<double>(statItem.second[0]);
254 uint16_t boardId = (statItem.first & 0xFFFF);
255 ss << "Crate: " << static_cast<int>(raw::getCrateId(boardId)) << " " << boardType << " board: " << static_cast<int>(raw::getLocId(boardId)) << " fraction of events not in sync: " << statItem.second[1] << " / " << statItem.second[0] << " = " << badFraction << std::endl;
256 }
257 return ss.str();
258}
259
260} // namespace mid
261} // namespace o2
Class to check the CRU user logic.
bool process(gsl::span< const ROBoard > bareData, gsl::span< const ROFRecord > bareRofs, gsl::span< const ROBoard > ulData, gsl::span< const ROFRecord > ulRofs, bool isFull=false)
std::string getSummary() const
GLboolean * data
Definition glcorearb.h:298
GLuint id
Definition glcorearb.h:650
bool isOk(ResultWas::OfType resultType)
uint8_t getCrateId(uint8_t uniqueLocId)
Definition ROBoard.h:75
bool isLoc(uint8_t statusWord)
Definition ROBoard.h:65
uint8_t getLocId(uint8_t uniqueLocId)
Definition ROBoard.h:80
bool isInside(double localX, double localY, const std::vector< PreCluster > &sortedPC, std::string &errorMsg)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
uint32_t orbit
LHC orbit.
uint16_t bc
bunch crossing ID of interaction
void setFromLong(int64_t l)
std::array< uint16_t, 4 > patternsNBP
Bending plane pattern.
Definition ROBoard.h:33
std::array< uint16_t, 4 > patternsBP
Fired chambers.
Definition ROBoard.h:32
uint8_t statusWord
Definition ROBoard.h:28
uint8_t boardId
Trigger word.
Definition ROBoard.h:30
uint8_t triggerWord
Status word.
Definition ROBoard.h:29
uint8_t firedChambers
Board ID in crate.
Definition ROBoard.h:31
std::vector< o2::ctf::BufferType > vec
o2::InteractionRecord ir(0, 0)