ATLAS Offline Software
Loading...
Searching...
No Matches
ITkPixelCsvWaferIdAlg.cxx
Go to the documentation of this file.
1/*
2Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
7
8
9#include "GaudiKernel/EventContext.h"
11
12#include <fstream>
13#include <sstream>
14#include <limits>
15#include <bit>
16
17
19 ISvcLocator* pSvcLocator)
20 : AthReentrantAlgorithm(name, pSvcLocator)
21{
22}
23
25 ATH_MSG_INFO("Initializing CsvWaferId algorithm");
26 ATH_CHECK(detStore()->retrieve(m_pixIdHelper, "PixelID"));
27 ATH_MSG_INFO("Retrieved PixelID helper");
29 ATH_MSG_INFO("Loaded CSV file");
30 return StatusCode::SUCCESS;
31}
32
33StatusCode ITkPixelCsvWaferIdAlg::execute(const EventContext& ctx) const {
34
35 ATH_CHECK ( ctx.valid() );
36
37 if (m_done.load(std::memory_order_acquire)) {
38 return StatusCode::SUCCESS;
39 }
40
41 bool expected = false;
42 if (!m_done.compare_exchange_strong(expected, true, std::memory_order_acq_rel)) {
43 return StatusCode::SUCCESS;
44 }
45
46 ATH_MSG_INFO("Executing CsvWaferId algorithm");
47
48 std::ofstream output(m_outputFile.value());
49 if (!output.good()) {
50 ATH_MSG_FATAL("Could not open wafer ID output file: " << m_outputFile.value());
51 return StatusCode::FAILURE;
52 }
53 output << "DetectorResourceID,True DetectorResourceID,FELIX Card Name,Uplink Pin,DMA buffer,SourceID\n";
54
55 std::vector<int> dma_buffer_vec = DmaBuffer();
56
57 for (size_t i = 0; i < m_rows.size(); ++i) {
58 const CsvRow& row = m_rows[i];
59 const auto w_and_fe_id = waferId(row);
60 const Identifier& id = std::get<0>(w_and_fe_id);
61 const int fe = std::get<1>(w_and_fe_id);
62 std::bitset<32> onlineId = std::get<2>(w_and_fe_id);
63 const std::string waferId_str = id.get_identifier32().getString();
64 const auto bec = m_pixIdHelper->barrel_ec(id);
65 const auto ld = m_pixIdHelper->layer_disk(id);
66 const auto phi = m_pixIdHelper->phi_module(id);
67 const auto eta = m_pixIdHelper->eta_module(id);
68
69 std::bitset<32> sID = sourceID( parseSPChain(row.spChain), row.md, row.fe, row.flx_card_device, dma_buffer_vec[i]);
70
71 std::string x = waferId_str.substr(0, waferId_str.length() - 2 );
72 std::stringstream ss;
73 ss << std::hex << x;
74 unsigned n;
75 ss >> n;
76 std::bitset<32> b(n);
77 b <<= 2; //shift left by two bits, to add FE bits
78 // Check bit position
79 bitcheck(b, 2, 25, "DetResID: Wafer ID");
80
81 std::bitset<32> febits = std::bitset<32>(fe);
82 // Check bit position
83 bitcheck(febits, 0, 1, "DetResID: Front-End ID");
84
85 b |= febits;
86
87 if (msgLvl(MSG::DEBUG)) {
88 output << waferId_str << "\t"
89 << x << "\t"
90 << b.to_string() << "\t"
91 << febits.to_string() << "\t"
92 << bec << "\t"
93 << ld << "\t"
94 << phi << "\t"
95 << eta << "\t"
96 << std::hex<< onlineId.to_ulong() << "\t";
97 }
98 //convert back to hex
99 std::stringstream res;
100 res << std::hex << std::uppercase << b.to_ulong();
101 // keep this, might be useful later
102 //output << res.str() << "\n";
103 output << std::hex << (b| onlineId).to_ulong() << ","
104 << (b| onlineId).to_ulong() << ","
105 << row.flx_card_device << ","
106 << row.fiber << ","
107 << dma_buffer_vec[i] << ","
108 << sID.to_ulong() << "\n";
109
110 }
111 output.close();
112 ATH_MSG_INFO("Wrote " << m_rows.size() << " wafer IDs to " << m_outputFile.value());
113
114 // Perform sanity checks
115 ATH_MSG_INFO("Performing sanity checks of " << m_outputFile.value());
117
118 return StatusCode::SUCCESS;
119}
120
122 const std::string resolvedCsv = PathResolver::find_file(m_csvFile.value(), "DATAPATH");
123 if (resolvedCsv.empty()) {
124 ATH_MSG_FATAL("Could not resolve CSV file: " << m_csvFile.value());
125 return StatusCode::FAILURE;
126 }
127 std::ifstream input(resolvedCsv);
128 if (!input.good()) {
129 ATH_MSG_FATAL("Could not open CSV file: " << resolvedCsv);
130 return StatusCode::FAILURE;
131 }
132 const std::string resolvedFelixCsv = PathResolver::find_file(m_FelixCardFile.value(), "DATAPATH");
133 if (resolvedFelixCsv.empty()) {
134 ATH_MSG_FATAL("Could not resolve FELIX CSV file: " << m_FelixCardFile.value());
135 return StatusCode::FAILURE;
136 }
137 std::ifstream inputFelix(resolvedFelixCsv);
138 if (!inputFelix.good()) {
139 ATH_MSG_FATAL("Could not open FELIX CSV file: " << resolvedFelixCsv);
140 return StatusCode::FAILURE;
141 }
142
143 //Load and store module CSV sheet
144 m_rows.clear();
145
146 ATH_MSG_INFO("Loading FE chips CSV");
147 std::string line;
148 bool firstLine = true;
149 while (std::getline(input, line)) {
150 if (line.empty()) {
151 continue;
152 }
153
154 if (firstLine) {
155 firstLine = false;
156 continue;
157 }
158 const std::vector<std::string> fields = splitCsvLine(line);
159 if (fields.size() < 5) {
160 ATH_MSG_WARNING("Skipping malformed Chips CSV line: " << line);
161 continue;
162 }
163
164 CsvRow row;
165 row.spChain = trim(fields[0]);
166 row.md = trim(fields[1]);
167 row.fe = std::stoi(trim(fields[2]));
168 row.flx_card_device = trim(fields[3]);
169 row.fiber = static_cast<unsigned int>(std::stoul(trim(fields[4])));
170
171 m_rows.push_back(std::move(row));
172 }
173
174 ATH_MSG_INFO("Loaded " << m_rows.size() << " Front-End Chips CSV rows from " << resolvedCsv);
175
176
177 //Load and store FELIX CSV sheet
178
179
180 m_felix_rows.clear();
181
182 ATH_MSG_INFO("Loading FELIX CSV");
183 firstLine = true;
184 while (std::getline(inputFelix, line)) {
185 if (line.empty()) {
186 continue;
187 }
188 if (firstLine) {
189 firstLine = false;
190 continue;
191 }
192 const std::vector<std::string> fields = splitCsvLine(line);
193 if (fields.size() < 3) {
194 ATH_MSG_WARNING("Skipping malformed FELIX CSV line: " << line);
195 continue;
196 }
197
198 FelixCsvRow row;
199 row.host = trim(fields[0]);
200 row.card1 = (unsigned int) std::stoi(trim(fields[1]));
201 row.card2 = (unsigned int) std::stoi(trim(fields[2]));
202 m_felix_rows.push_back(std::move(row));
203 }
204
205 ATH_MSG_INFO("Loaded " << m_felix_rows.size() << " FELIX CSV rows from " << resolvedFelixCsv);
206 return StatusCode::SUCCESS;
207}
208
209std::tuple< Identifier, int, std::bitset<32> > ITkPixelCsvWaferIdAlg::waferId(const CsvRow& row) const {
210 ATH_MSG_DEBUG("waferId lookup for SP chain " << row.spChain
211 << ", module " << row.md << ", FE " << row.fe);
212
213 //SP chain is like G-IS-L05-R05-A-SP2
214 std::vector<std::string> spChain_cur = parseSPChain(row.spChain);
215
216 int bec = barrel_ec(spChain_cur);
217 int ld = layer_disk(spChain_cur);
218 int phi = phi_module(spChain_cur, row.md, row.fe );
219 int eta = eta_module(spChain_cur, row.md, row.fe );
220 int fe_n = feID(spChain_cur, row.fe );
221 std::bitset<32> online_id = onlineId(spChain_cur, row.md, row.fe);
222
223 return std::make_tuple(m_pixIdHelper->wafer_id(bec, ld, phi, eta), fe_n, online_id);
224}
225
226std::string ITkPixelCsvWaferIdAlg::trim(const std::string& input) {
227 const auto begin = input.find_first_not_of(" \t\r\n");
228 if (begin == std::string::npos) {
229 return "";
230 }
231
232 const auto end = input.find_last_not_of(" \t\r\n");
233 return input.substr(begin, end - begin + 1);
234}
235
236std::vector<std::string> ITkPixelCsvWaferIdAlg::splitCsvLine(const std::string& line) {
237 std::vector<std::string> fields;
238 std::stringstream ss(line);
239 std::string field;
240
241 while (std::getline(ss, field, ',')) {
242 fields.push_back(field);
243 }
244 return fields;
245}
246
247std::vector<std::string> ITkPixelCsvWaferIdAlg::parseSPChain(const std::string& spChain) {
248 std::vector<std::string> elements;
249 std::stringstream ss(spChain);
250 std::string element;
251
252 while (std::getline(ss, element, '-')) {
253 elements.push_back(element);
254 }
255
256 return elements;
257}
258
259
260int ITkPixelCsvWaferIdAlg::barrel_ec(const std::vector<std::string>& spchain) const {
261
262 if (spchain[1] == "IS" &&
263 (spchain[2] == "L0" || spchain[2] == "L1") &&
264 spchain.at(3)[0] != 'R') { // inner flat barrel
265 return 0;
266 }
267 else if (spchain[1] == "OB" &&
268 (spchain[2] == "L2" || spchain[2] == "L3" ||
269 spchain[2] == "L4") &&
270 (spchain.at(3)[0] == 'B')) { // Outer flat barrel has 3 layers
271 return 0;
272 }
273 else{
274 //Need to calculat the side sign because eta is always positive.
275 std::string sideAC = spchain[4];
276 if(sideAC != "A" && sideAC != "C"){
277 sideAC = spchain[5];
278 }
279 int side = (sideAC == "A")? 1 : -1; // A for side pos, C for side neg
280 return side*2; // endcap is +2 or -2 - this includes barrel rings, in offline they are treated as endcap
281 }
282}
283
284int ITkPixelCsvWaferIdAlg::layer_disk(const std::vector<std::string>& spchain) const {
285 int b_ec = barrel_ec(spchain);
286 if( b_ec == 0 ){ // flat barrel
287 return spchain.at(2)[1] - '0';
288 }
289 else{ // endcap and barrel rings - all considered as 'endcap' disks
290 if (spchain[2] == "L01" &&
291 (spchain.at(5) == "SP1" || spchain.at(5) == "SP3")) { // barrel vertical small combined rings, disk 0
292 ATH_MSG_DEBUG("added layer 0 barrel vertical combined ring: SP chain "
293 << spchain[1]<< spchain[2]<< spchain[3]<< spchain[4]<< spchain[5]);
294 return 0;
295 }
296 else if (spchain[2] == "L01" &&
297 (spchain.at(5) == "SP2" || spchain.at(5) == "SP4")) { // barrel vertical large combined rings, disk 2
298 return 2;
299 }
300 else if(spchain[1] == "OB" && (spchain[2] == "L2" || //OB inclined rings, disks 3, 5, 7
301 spchain[2] == "L3" ||
302 spchain[2] == "L4") ){
303 return (2* ((spchain.at(2))[1] -'0') - 1);
304 }
305 else if(spchain[1] == "IS" && spchain[2] == "L05"){
306 return 1; // end-cap rings, inner system, disk 1
307 }
308 else if(spchain[1] == "IS" && spchain[2] == "L1"){
309 return 2; // end-cap rings, inner system, layer 2
310 }
311 else if(spchain[1] == "EC"){ //outer end-cap
312 return 2* (spchain.at(2)[1]-'0'); // disks 4, 6, 8
313 }
314 else{
315 ATH_MSG_WARNING("Bad values in layer_disk function, return -9999");
316 return -9999;
317 }
318 }
319}
320
321int ITkPixelCsvWaferIdAlg::phi_module(const std::vector<std::string>& spchain, const std::string& mod, int fe ) const {
322
323 int b_ec = barrel_ec(spchain);
324 int ld = layer_disk(spchain);
325
326 if( b_ec == 0 ){ // flat barrel
327 std::string phi_str = (spchain.at(3)).substr(1,2);
328 if(ld == 0 || ld ==1 ){ //inner system flat barrel
329 return std::stoi(phi_str) - 1;
330 }
331 else{ //outer flat barrel
332 int phi = std::stoi(phi_str) - 1 ;
333 phi = (mod[2] == 'T') ? 2*phi + 1 : 2*phi;
334 return phi;
335 }
336 }
337 else{ // endcap and barrel rings - all considered as disks
338 if (ld == 0) { // barrel vertical small combined rings, disk 0
339 std::string sp_str(1, (spchain.at(5)[2])); // SP=1 and SP=3 alternate in phi
340 if(sp_str == "1"){
341 ATH_MSG_DEBUG( "return phi = " << 6 * (stoi(mod) - 1 ) + 2 * (fe - 1));
342 return 6 * (stoi(mod) - 1 ) + 2 * (fe - 1); // probably wrong offset, TOCHECK
343 }
344 else if(sp_str == "3"){
345 ATH_MSG_DEBUG( "return phi = " << 6 * (stoi(mod) - 1 ) + 2 * (fe - 1) + 1);
346 return 6 * (stoi(mod) - 1 ) + 2 * (fe - 1) + 1; // probably wrong offset, TOCHECK
347 }
348 else{
349 ATH_MSG_WARNING("Bad input for phi_module,return -9999 ");
350 return -9999;
351 }
352 }
353 else if (spchain[2] == "L01" &&
354 (spchain.at(5) == "SP2" || spchain.at(5) == "SP4")) {
355 // barrel vertical large combined rings (quad modules), disk 2
356 std::string sp_str(1, spchain.at(5)[2]); // SP=2 and SP=4 alternate in phi
357 if(sp_str == "2"){
358 return 2 * (stoi(mod) - 1 ) ; // probably wrong offset, TODO need to revisit
359 }
360 else if(sp_str == "4"){
361 return 2 * (stoi(mod) - 1 ) + 1; // probably wrong offset, TODO need to revisit
362 }
363 else{
364 ATH_MSG_WARNING("Bad input for phi_module,return -9999 ");
365 return -9999;
366 }
367 }
368 //barrel inclined rings
369 else if(ld == 3 || ld == 5 || ld ==7){ //OB inclined rings, disks 3, 5, 7
370 std::string phi_str = mod.substr(2,2);
371 int phi = std::stoi(phi_str)-1;
372 return phi;
373 }
374 else if(ld == 1){ //end-cap intermediate rings, inner system, disk 1 - triplets: one module per FE /!\ 0-17
375 return 6 * (stoi(mod) - 1 ) + 2 * (fe - 1); // probably wrong offset, TODO need to revisit
376 }
377 else if(ld == 2){ // end-cap rings, inner system, layer 2 // 0-19
378 std::string sp_str(1, spchain.at(5)[2]); // SP=1 and SP=2 alternate in phi
379 if(sp_str == "1"){
380 return 2 * (stoi(mod) - 1 ) ; // probably wrong offset, TODO need to revisit
381 }
382 else if(sp_str == "2"){
383 return 2 * (stoi(mod) - 1 ) + 1; // probably wrong offset, TODO need to revisit
384 }
385 }
386 else if(ld == 4 || ld == 6 || ld ==8){ //Outer EC disks 4, 6, 8
387 std::string phi_str = mod.substr(2,2);
388 int phi = std::stoi(phi_str) - 1;
389 return phi;
390 }
391 else{
392 ATH_MSG_WARNING("Bad input for phi_module,return -9999 ");
393 return -9999;
394 }
395 }
396 return -9999;
397}
398
399
400int ITkPixelCsvWaferIdAlg::eta_module(const std::vector<std::string>& spchain, const std::string& mod, int fe) const {
401 int b_ec = barrel_ec(spchain);
402 int ld = layer_disk(spchain);
403 int side = (spchain[4] == "A") ? 1 : -1; // A for side pos, C for side neg
404
405 if( b_ec == 0 ){ // flat barrel
406 if(ld ==0){ //triplets, one front-end is considered as one module
407 return side * (3 * (std::stoi(mod) -1) + fe );
408 }
409 else if(ld == 1){
410 return side * std::stoi(mod);
411 }
412 else if(ld < 5){
413 std::string eta_str(1, mod[4]);
414 int eta = std::stoi(eta_str);
415 return side * eta;
416 }
417 else{
418 ATH_MSG_WARNING("Bad layer for flat barrel: " << ld);
419 return -9999;
420 }
421 }
422 //barrel rings and end caps - all considered as disks
423 else{
424 if(spchain[2] == "L01"){ // barrel vertical small and large combined rings, disk 0
425 std::string eta_str = (spchain.at(3)).substr(1,2);
426 return std::stoi(eta_str)-1;
427 }
428 else if(ld == 3 || ld == 5 || ld ==7){ //OB inclined rings, disks 3, 5, 7
429 std::string eta_str = (spchain.at(3)).substr(1,2);
430 return std::stoi(eta_str) - 1 ;
431 }
432 else if(ld == 1){ //end-cap rings, inner system, disk 1 (L05) - triplets: one module per FE
433 std::string eta_str = (spchain.at(3)).substr(1,2);
434 return std::stoi(eta_str) - 1;
435 }
436 else if(ld == 2){ // end-cap rings, inner system, disk 2 - eta from 15 to 22
437 std::string eta_str = (spchain.at(3)).substr(1,2);
438 return std::stoi(eta_str) + 14 ;
439 }
440 else if(ld == 4 || ld == 6 || ld ==8){ //Outer EC disks 4, 6, 8
441 std::string eta_str = (spchain.at(3)).substr(1,2);
442 return std::stoi(eta_str) - 1 ;
443 }
444 else{
445 ATH_MSG_WARNING("Bad input for eta_module,return -9999 ");
446 return -9999;
447 }
448 }
449 return -9999;
450}
451
452
453int ITkPixelCsvWaferIdAlg::feID(const std::vector<std::string>& spchain, int fe) const {
454 int b_ec = barrel_ec(spchain);
455 int ld = layer_disk(spchain);
456 if(ld ==0 || (ld == 1 && std::abs(b_ec) == 2 ) ){ //triplets
457 return 0;
458 }
459 else{ // quads
460 return fe-1;
461 }
462
463}
464
465
466std::bitset<32> ITkPixelCsvWaferIdAlg::onlineId(const std::vector<std::string>& spchain, const std::string& mod, int fe, bool legacy) const {
467 // onlineID = chipID (4b) chipID ON/OFF (1b) RD53C/BCID (1b)
468 std::bitset<32> febits(0);
469 int ld = layer_disk(spchain);
470 int fe_id = feID(spchain, fe);
471 int b_ec = barrel_ec(spchain);
472 int etamod = eta_module(spchain, mod, fe);
473
474 //these bits encode the merging scheme of modules
475 if( b_ec == 0 ){ // barrel
476 if(ld == 1 || ld ==2 ){ //L1, L2 flat, 4 to 2 merging
477 if(fe_id < 2){
478 febits = legacy ? std::bitset<32>(0x30000000) : std::bitset<32>(0x10000000) ;
479 }
480 else{
481 febits = legacy ? std::bitset<32>(0xC0000000) : std::bitset<32>(0x20000000) ;
482 }
483 }
484 if(ld == 3 || ld == 4 ){ //L3, L4 flat, 4 to 1 merging
485 febits = legacy ? std::bitset<32>(0xF0000000) : std::bitset<32>(0x30000000) ;
486 }
487 }
488 else{
489 if(ld == 3){ // Barrel ring L2
490 if(fe_id < 2){
491 febits = legacy ? std::bitset<32>(0x30000000) : std::bitset<32>(0x10000000) ;
492 }
493 else{
494 febits = legacy ? std::bitset<32>(0xC0000000) : std::bitset<32>(0x20000000) ;
495 }
496 }
497 if(ld == 5 || ld ==7){ // Barrel rings L3, L4
498 febits = legacy ? std::bitset<32>(0xF0000000) : std::bitset<32>(0x30000000) ;
499 }
500 if(ld == 4 && etamod < 5){ // first half of EC L2
501 if(fe_id < 2){
502 febits = legacy ? std::bitset<32>(0x30000000) : std::bitset<32>(0x10000000) ;
503 }
504 else{
505 febits = legacy ? std::bitset<32>(0xC0000000) : std::bitset<32>(0x20000000) ;
506 }
507 }
508 if(ld == 6){ // EC L3
509 if(fe_id < 2){
510 febits = legacy ? std::bitset<32>(0x30000000) : std::bitset<32>(0x10000000) ;
511 }
512 else{
513 febits = legacy ? std::bitset<32>(0xC0000000) : std::bitset<32>(0x20000000) ;
514 }
515 }
516 if(ld == 8 && etamod < 7){ // EC L4, 1-7
517 febits = legacy ? std::bitset<32>(0xF0000000) : std::bitset<32>(0x30000000) ;
518 }
519 if(ld == 8 && etamod >= 7){ // EC L4, 8-9
520 if(fe_id < 2){
521 febits = legacy ? std::bitset<32>(0x30000000) : std::bitset<32>(0x10000000) ;
522 }
523 else{
524 febits = legacy ? std::bitset<32>(0xC0000000) : std::bitset<32>(0x20000000) ;
525 }
526 }
527 }
528 //add the chip ID ON/OFF (1b) and RD53c or BCID (1b) bits
529 febits |= std::bitset<32>("00001100000000000000000000000000");
530
531 bitcheck(febits, 26, 29, "DetResID: Online ID");
532
533 return febits;
534}
535
536
537std::vector<int> ITkPixelCsvWaferIdAlg::DmaBuffer() const {
538 std::vector<int> dmaNumbers;
539 dmaNumbers.reserve(m_rows.size());
540
541 size_t i = 0;
542 while (i < m_rows.size()) {
543 const std::string& card = m_rows[i].flx_card_device;
544 size_t j = i;
545 unsigned int minFiber = std::numeric_limits<unsigned int>::max();
546 for (; j < m_rows.size() ; ++j) {
547 if(m_rows[j].flx_card_device != card){
548 continue;
549 }
550 if (m_rows[j].fiber > 0 && m_rows[j].fiber < minFiber){
551 minFiber = m_rows[j].fiber;
552 }
553 }
554
555 if (minFiber == std::numeric_limits<unsigned int>::max()) {
556 // no valid fiber found in this block, assign 9
557 for (size_t k = i; k < j; ++k){
558 dmaNumbers.push_back(9);
559 }
560 i = j;
561 continue;
562 }
563
564 // assign DMA groups based on minFiber, groups of 3 fibers -> DMA 0..3
565 for (size_t k = i; k < j; ++k) {
566 int dma = 0;
567 if (m_rows[k].fiber >= minFiber) {
568 const int offset = static_cast<int>(m_rows[k].fiber) - static_cast<int>(minFiber);
569 // 3 fibers per DMA buffer except for L0 flat barrel (4 lanes FE --> 2 fibers)
570 int b_ec = barrel_ec(parseSPChain(m_rows[k].spChain));
571 int ld = layer_disk(parseSPChain(m_rows[k].spChain));
572 if(b_ec == 0 && ld ==0){
573 dma = offset / 2;
574 }
575 else{
576 dma = offset / 3;
577 }
578 }
579 if (dma < 0){
580 ATH_MSG_WARNING("Assigned DMA buffer goes negative: " << dma);
581 }
582 if (dma > 3){
583 ATH_MSG_WARNING("Assigned DMA buffer goes higher than 3: for card "
584 << card << " ; nDMAs =" << dma << ", line " << k );
585
586 }
587 dmaNumbers.push_back(std::move(dma));
588 }
589 i = j;
590 }
591 return dmaNumbers;
592}
593
594
595std::bitset<32> ITkPixelCsvWaferIdAlg::sourceID(const std::vector<std::string>& spchain, const std::string& mod, int fe, const std::string& flx, const unsigned int dma) const {
596 // ((subdetector ID) << 16) |((FELIX card ID) << 8) | ((FELIX device ID) << 7) | ((DMA buffer number) << 5)
597
598 int b_ec = barrel_ec(spchain);
599 int ld = layer_disk(spchain);
600 int etamod = eta_module(spchain, mod, fe);
601
602 std::bitset<32> b(0);
603 std::bitset<32> subdet = subDetID(b_ec, ld, etamod);
604 subdet <<= 16 ; //shift left by 16 bits
605
606 bitcheck(subdet, 16, 23, "SourceID : SubDetectorID " );
607
608 std::vector<std::string> flx_card_device = splitFLX_card_device(flx);
609 auto hostIndex = flxHost((unsigned int) std::stoi(flx_card_device[0]));
610 std::bitset<32> flx_host = std::bitset<32>(hostIndex.first);
611 flx_host <<= 8; //shift left by 8 bits
612 bitcheck(flx_host, 8, 15, "SourceID : FELIX host " );
613
614 std::bitset<32> flxCard = std::bitset<32>(hostIndex.second);
615 flxCard <<= 5; //shift left by 5 bits
616 bitcheck(flxCard, 5, 5, "SourceID : FELIX card " );
617
618 std::bitset<32> flxDev = std::bitset<32>(std::stoi(flx_card_device[1]) - 1 );
619 flxDev <<= 4; //shift left by 6 bits
620 bitcheck(flxDev, 4, 4, "SourceID : card device " );
621
622 std::bitset<32> dma_b = std::bitset<32>(dma);
623 //dma_b <<= 4; //shift left by 4 bits
624 bitcheck(dma_b, 0, 1, "SourceID : DMA buffer index " );
625
626 b = subdet | flx_host | flxCard | flxDev | dma_b;
627 return b;
628}
629
630
631
632std::vector<std::string> ITkPixelCsvWaferIdAlg::splitFLX_card_device(const std::string& s) const {
633 std::vector<std::string> fields;
634 std::stringstream ss(s);
635 std::string field;
636
637 while (std::getline(ss, field, '.')) {
638 fields.push_back(field);
639 }
640 if (fields.size() !=2){
641 ATH_MSG_ERROR("Wrong FLX_card_device input: " << s);
642 }
643 if (fields[1] !="1" && fields[1] !="2" ){
644 ATH_MSG_ERROR("Wrong FLX device input: " << fields[1]);
645 }
646 return fields;
647}
648
649
650std::bitset<32> ITkPixelCsvWaferIdAlg::subDetID(int barrel_endcap, int layer_disk, int eta) const {
651 if(barrel_endcap == 0){
652 if(layer_disk < 2){
653 if(eta > 0 ){
654 return std::bitset<32>(0x90); // Inner barrel A
655 }
656 else{
657 return std::bitset<32>(0x91); // Inner barrel C
658 }
659 }
660 else{
661 if(eta > 0){
662 return std::bitset<32>(0x92); // Outer Barrel A
663 }
664 else{
665 return std::bitset<32>(0x93); // Outer Barrel C
666 }
667 }
668 }
669 else if(barrel_endcap == 2){
670 if(layer_disk == 0 || (layer_disk == 2 && eta < 15)){
671 return std::bitset<32>(0x90); // Inner barrel A
672 }
673 else if(layer_disk == 3 || layer_disk == 5 || layer_disk == 7){
674 return std::bitset<32>(0x92); // Outer barrel A
675 }
676 else if(layer_disk == 1 || (layer_disk == 2 || eta >=15 ) ){
677 return std::bitset<32>(0x94); // Inner end-cap A
678 }
679 else if(layer_disk == 4 || layer_disk == 6 || layer_disk == 8){
680 return std::bitset<32>(0x96); // Outer end-cap A
681 }
682 else{
683 ATH_MSG_ERROR("Wrong barrel_endcap / layer_disk / eta_mod values ");
684 ATH_MSG_ERROR("return subDetectorID =0 " );
685 return std::bitset<32>(0);
686 }
687 }
688 else if(barrel_endcap == -2){
689 if(layer_disk == 0 || (layer_disk == 2 && eta < 15)){
690 return std::bitset<32>(0x91); // Inner barrel C
691 }
692 else if(layer_disk == 3 || layer_disk == 5 || layer_disk == 7){
693 return std::bitset<32>(0x93); // Outer barrel C
694 }
695 else if(layer_disk == 1 || (layer_disk == 2 || eta >=15 ) ){
696 return std::bitset<32>(0x95); // Inner end-cap C
697 }
698 else if(layer_disk == 4 || layer_disk == 6 || layer_disk == 8){
699 return std::bitset<32>(0x97); // Outer end-cap C
700 }
701 else{
702 ATH_MSG_ERROR("Wrong barrel_endcap / layer_disk / eta_mod values ");
703 ATH_MSG_ERROR("return subDetectorID =0 " );
704 return std::bitset<32>(0);
705 }
706 }
707 else{
708 ATH_MSG_ERROR("Wrong barrel_endcap value: " << barrel_endcap);
709 ATH_MSG_ERROR("return subDetectorID =0 " );
710 return std::bitset<32>(0);
711 }
712
713}
714
715
716const StatusCode ITkPixelCsvWaferIdAlg::sanityCheck(const std::string & s, bool legacy) const {
717
718 std::ifstream fcheck(s);
719 if (!fcheck.good()) {
720 ATH_MSG_FATAL("Could not open output file: " << s);
721 return StatusCode::FAILURE;
722 }
723
724 // Read all rows, fill a vector with the full info
725
726 std::string line;
727 bool firstLine = true;
728 std::vector < OutputCsvRow > rowVec;
729 while (std::getline(fcheck, line)) {
730 if (line.empty()) {
731 continue;
732 }
733 if (firstLine) {
734 firstLine = false;
735 continue;
736 }
737 const std::vector<std::string> fields = splitCsvLine(line);
738 if (fields.size() < 6) {
739 ATH_MSG_WARNING("Skipping malformed Chips CSV line: " << line);
740 continue;
741 }
742 OutputCsvRow row;
743
744 const auto parseHex = [](const std::string& value) -> unsigned int {
745 std::istringstream iss(value);
746 iss >> std::hex;
747 unsigned int parsed = 0;
748 iss >> parsed;
749 return parsed;
750 };
751
752 row.detResId = std::bitset<32>(parseHex(fields[0]));
753 row.tdetResId = std::bitset<32>(parseHex(fields[1]));
754 row.card_dev = fields[2];
755 row.fiber = parseHex(fields[3]);
756 row.dma = std::stoi(fields[4]);
757 row.sourceId = std::bitset<32>(parseHex(fields[5]));
758 rowVec.push_back(std::move(row));
759 line = "";
760 }
761
762 // Now, perform the checks
763 size_t i = 0;
764 std::vector<std::string > cards;
765 while (i < rowVec.size()) {
766 const std::string& card = rowVec[i].card_dev;
767 if(std::find(cards.begin(), cards.end(), card) != cards.end()) {
768 continue; // already checked that FELIX device
769 }
770 cards.push_back(card);
771
772
773 std::map < int, float> fiber_links_map ;
774 std::map < int, int> fiber_dma_map ;
775 int dma_nfiber[4] = {};
776
777 size_t j = i;
778 for (; j < rowVec.size() ; ++j) {
779 if(rowVec[j].card_dev != card){
780 continue;
781 }
782
783 fiber_dma_map[rowVec[j].fiber] = rowVec[j].dma ;
784 // 1. Check that there are <= 12 fibers for one device
785 if(rowVec[j].fiber > 12){
786 ATH_MSG_WARNING("Sanity check of file " << s << " : Bad number of fibers, line: " << j );
787 ATH_MSG_WARNING("Nfiber = " << rowVec[j].fiber);
788 }
789 if(legacy){
790 if( (rowVec[j].detResId & std::bitset<32>(0xf0000000)) == std::bitset<32>(0xf0000000) ){
791 fiber_links_map[rowVec[j].fiber] += 0.25;
792 }
793 else if( (rowVec[j].detResId & std::bitset<32>(0xf0000000)) == std::bitset<32>(0xc0000000) ||
794 (rowVec[j].detResId & std::bitset<32>(0xf0000000)) == std::bitset<32>(0x30000000)) {
795 fiber_links_map[rowVec[j].fiber] += 0.5;
796 }
797 else if( (rowVec[j].detResId & std::bitset<32>(0xf0000000)) == std::bitset<32>(0x00000000)) {
798 fiber_links_map[rowVec[j].fiber] += 1;
799 }
800 else{
801 ATH_MSG_WARNING("Sanity check of file " << s << " : Bad Chip ID value in DetResID, line: " << j );
802 }
803 }
804 else{
805 if( (rowVec[j].detResId & std::bitset<32>(0xf0000000)) == std::bitset<32>(0x30000000) ){
806 fiber_links_map[rowVec[j].fiber] += 0.25;
807 }
808 else if( (rowVec[j].detResId & std::bitset<32>(0xf0000000)) == std::bitset<32>(0x20000000) ||
809 (rowVec[j].detResId & std::bitset<32>(0xf0000000)) == std::bitset<32>(0x10000000)) {
810 fiber_links_map[rowVec[j].fiber] += 0.5;
811 }
812 else if( (rowVec[j].detResId & std::bitset<32>(0xf0000000)) == std::bitset<32>(0x00000000)) {
813 fiber_links_map[rowVec[j].fiber] += 1;
814 }
815 else{
816 ATH_MSG_WARNING("Sanity check of file " << s << " : Bad Chip ID value in DetResID, line: " << j );
817 }
818 }
819 }
820
821 // 2. Check that there are <= 6 lpGBT links per fiber
822 for ( const auto & p : fiber_links_map ) {
823 if(ceilf(p.second) != p.second){
824 ATH_MSG_WARNING("Sanity check of file " << s << " : Card.device = "
825 << card << " ; Fiber " << p.first << "N links = " << p.second );
826 }
827 if( p.second > 6){
828 ATH_MSG_WARNING("More than 6 physical lpGBT links, file " << s << " : Card.device = "
829 << card << " ; Fiber " << p.first << " ; N links = " << p.second );
830 }
831 }
832 // 3. Check that there are <= 3 fibers per DMA buffer
833
834 for ( const auto & p : fiber_dma_map ) {
835
836 if( p.second > 3){
837 ATH_MSG_WARNING("DMA buffer index higher than 3, file " << s << " : Card.device = "
838 << card << " ; DMA " << p.second << " ; fiber = " << p.first );
839 continue;
840 }
841 dma_nfiber[p.second] ++;
842 }
843 for (std::size_t g = 0; g < std::size(dma_nfiber); ++g) {
844 if(dma_nfiber[g] > 3){
845 ATH_MSG_WARNING("More than 3 fibers, file " << s << " : Card.device = "
846 << card << " ; DMA " << g << " ; N fibers = " << dma_nfiber[g] );
847 }
848 }
849 i = j;
850 }
851
852 fcheck.close();
853 return StatusCode::SUCCESS;
854
855}
856
857
858
859
860void ITkPixelCsvWaferIdAlg::bitcheck(std::bitset<32> b, uint32_t lsb_lim, uint32_t msb_lim , std::string_view s) const {
861
862 uint32_t x = static_cast<uint32_t> (b.to_ulong());
863 if(x!=0){
864 uint32_t lsb_used = std::countr_zero(x);
865 uint32_t msb_used = std::bit_width(x) - 1;
866
867 if( (msb_used > msb_lim) || (lsb_used < lsb_lim) ){
868 ATH_MSG_WARNING("Bits used for this ID (" << s << ") are not correctly set");
869 ATH_MSG_WARNING(" MSB used = " << msb_used << " MSB allowed = " << msb_lim);
870 ATH_MSG_WARNING(" LSB used = " << lsb_used << " LSB allowed = " << lsb_lim);
871 ATH_MSG_WARNING("Full bitset = " << b.to_string());
872 }
873 }
874}
875
876
877std::pair <unsigned int, unsigned int> ITkPixelCsvWaferIdAlg::flxHost(unsigned int card) const {
878 auto it1 = std::find_if(m_felix_rows.begin(), m_felix_rows.end(),
879 [card](const FelixCsvRow& p) {
880 return (p.card1 == card);
881 });
882 auto it2 = std::find_if(m_felix_rows.begin(), m_felix_rows.end(),
883 [card](const FelixCsvRow& p) {
884 return (p.card2 == card);
885 });
886 auto it = (it1 != m_felix_rows.end()) ? it1 : ( (it2 != m_felix_rows.end()) ? it2 : m_felix_rows.end());
887 unsigned int Ncard = (it1 != m_felix_rows.end()) ? 0 : ( (it2 != m_felix_rows.end()) ? 1 : 0 );
888 if (it != m_felix_rows.end()) {
889 std::size_t index = it - m_felix_rows.begin();
890 std::string s= m_felix_rows[index].host;
891 //Ex: pc-tdq-ro-pix-is-a-15, need to return 15
892 std::size_t pos = s.rfind('-');
893 return (pos == std::string::npos) ? std::pair <unsigned int, unsigned int>(0,0) : std::pair <unsigned int, unsigned int>(std::stoi(s.substr(pos + 1)), Ncard);
894 }
895 else{
896 ATH_MSG_WARNING("Couldn't find a host for card number " << card << ", returning (0, 0)");
897 return std::pair <unsigned int, unsigned int>(0, 0);
898 }
899}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
std::pair< std::vector< unsigned int >, bool > res
static Double_t ss
This is an Identifier helper class for the Pixel subdetector.
#define x
const ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
An algorithm that can be simultaneously executed in multiple threads.
virtual StatusCode initialize() override
virtual StatusCode execute(const EventContext &ctx) const override
static std::string trim(const std::string &input)
std::vector< std::string > splitFLX_card_device(const std::string &s) const
static std::vector< std::string > splitCsvLine(const std::string &line)
void bitcheck(std::bitset< 32 > b, uint32_t lsb_lim, uint32_t msb_lim, std::string_view s="") const
std::vector< int > DmaBuffer() const
std::pair< unsigned int, unsigned int > flxHost(unsigned int card) const
Gaudi::Property< std::string > m_FelixCardFile
std::vector< CsvRow > m_rows
int phi_module(const std::vector< std::string > &spchain, const std::string &mod, int fe) const
Gaudi::Property< std::string > m_outputFile
static std::vector< std::string > parseSPChain(const std::string &spChain)
int feID(const std::vector< std::string > &spchain, int fe) const
Gaudi::Property< std::string > m_csvFile
std::bitset< 32 > onlineId(const std::vector< std::string > &spchain, const std::string &mod, int fe, bool legacy=false) const
std::vector< FelixCsvRow > m_felix_rows
int barrel_ec(const std::vector< std::string > &spchain) const
std::tuple< Identifier, int, std::bitset< 32 > > waferId(const CsvRow &row) const
std::bitset< 32 > subDetID(int barrel_endcap, int layer_disk, int eta) const
const StatusCode sanityCheck(const std::string &s, bool legacy=false) const
std::bitset< 32 > sourceID(const std::vector< std::string > &spchain, const std::string &mod, int fe, const std::string &flx, const unsigned int dma) const
int eta_module(const std::vector< std::string > &spchain, const std::string &mod, int fe) const
ITkPixelCsvWaferIdAlg(const std::string &name, ISvcLocator *pSvcLocator)
int layer_disk(const std::vector< std::string > &spchain) const
static std::string find_file(const std::string &logical_file_name, const std::string &search_path)
Definition index.py:1