Belle II Software development
Unpacker.h
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#include <string>
9#include <sstream>
10#include <iostream>
11#include <iomanip>
12#include <bitset>
13#include <numeric>
14#include <cmath>
15#include <algorithm>
16
17#include <trg/cdc/dataobjects/Bitstream.h>
18#include <trg/cdc/dataobjects/CDCTriggerTrack.h>
19#include <trg/cdc/dataobjects/CDCTriggerSegmentHit.h>
20#include <trg/cdc/dataobjects/CDCTriggerFinderClone.h>
21#include <trg/cdc/dataobjects/CDCTriggerMLPInput.h>
22#include <framework/gearbox/Const.h>
23#include <trg/cdc/dbobjects/CDCTriggerNeuroConfig.h>
24#include <framework/dataobjects/BinnedEventT0.h>
25
26namespace Belle2 {
32 namespace CDCTriggerUnpacker {
33
34 constexpr double pi() { return std::atan(1) * 4; }
35
36 // constants
37 static constexpr std::array<int, 9> nMergers = {10, 10, 12, 14, 16, 18, 20, 22, 24};
38
39 // The data width are the specs under full speed.
40 // When using one of the half-speed version,
41 // TS/track are filled from MSB, leaving LSB blank.
42 static constexpr int TSFOutputWidth = TSF_TO_2D_WIDTH; // 429 (#defined in Bitstream.h)
43 static constexpr int nTrackers = NUM_2D; // 4
44 static constexpr int nAxialTSF = NUM_TSF; // 5
45 static constexpr int nStereoTSF = 4;
46 static constexpr int T2DOutputWidth = T2D_TO_3D_WIDTH; // 747
47 static constexpr unsigned lenTS = 21; // ID (8 bit) + t (9 bit) + LR (2 bit) + priority (2 bit)
48
49 static constexpr int nMax2DTracksPerClock = 4;
50
51 // bit width of the clock counter
52 static constexpr int clockCounterWidth = 9;
53
54 /* number of mergers in axial super layers */
55 static constexpr std::array<int, nAxialTSF> nAxialMergers = {10, 12, 16, 20, 24};
56 /* number of wires in a super layer*/
57 static constexpr std::array<int, 9> nWiresInSuperLayer = {
58 160, 160, 192, 224, 256, 288, 320, 352, 384
59 };
60 /* Number of wire/cells in a single layer per merger unit */
61 static constexpr int nCellsInLayer = 16;
62
63 // dataobjects
64 using TSFOutputVector = std::array<char, TSFOutputWidth>;
65 using TSFOutputArray = std::array<TSFOutputVector, nTrackers>;
66 using TSFOutputBus = std::array<TSFOutputArray, nAxialTSF>;
67 using TSFOutputBitStream = Bitstream<TSFOutputBus>;
68
69 using T2DOutputVector = std::array<char, T2DOutputWidth>;
70 using T2DOutputBus = std::array<T2DOutputVector, nTrackers>;
71 using T2DOutputBitStream = Bitstream<T2DOutputBus>;
72
73 using NNVector = std::array<char, NN_WIDTH>;
74 using NNBus = std::array<NNVector, nTrackers>;
75 using NNBitStream = Bitstream<NNBus>;
76 // using NNInputVector = std::array<char, NNInputWidth>;
77 // using NNInputBus = std::array<NNInputVector, nTrackers>;
78 // using NNInputBitStream = Bitstream<NNInputBus>;
79
80 // using NNOutputVector = std::array<char, NNOutputWidth>;
81 // using NNOutputBus = std::array<NNOutputVector, nTrackers>;
82 // using NNOutputBitStream = Bitstream<NNOutputBus>;
83
84 // functions
85 std::string padto(std::string s, unsigned l)
86 {
87 if (s.size() < l) {
88 s.insert(s.begin(), l - s.size(), ' ');
89 }
90 return s;
91 }
92 std::string padright(std::string s, unsigned l)
93 {
94 if (s.size() < l) {
95 s.insert(s.end(), l - s.size(), ' ');
96 }
97 return s;
98 }
99
100 void printBuffer(int* buf, int nwords)
101 {
102 for (int j = 0; j < nwords; ++j) {
103 printf(" %.8x", buf[j]);
104 if ((j + 1) % 8 == 0) {
105 printf("\n");
106 }
107 }
108 printf("\n");
109 return;
110 };
111
112 std::string rawIntToAscii(int buf)
113 {
114 std::ostringstream firmwareTypeStream;
115 firmwareTypeStream << std::hex << buf;
116 std::string firmwareTypeHex(firmwareTypeStream.str());
117 std::string firmwareType(4, '0');
118 for (int i = 0; i < 4; i++) {
119 std::istringstream firmwareTypeIStream(firmwareTypeHex.substr(i * 2, 2));
120 int character;
121 firmwareTypeIStream >> std::hex >> character;
122 firmwareType[i] = character;
123 }
124 return firmwareType;
125 };
126
127 std::string rawIntToString(int buf)
128 {
129 std::ostringstream firmwareVersionStream;
130 firmwareVersionStream << std::hex << buf;
131 return firmwareVersionStream.str();
132 };
133
134 /* Note: VHDL std_logic value is stored in a byte (char). The
135 * 9 values are mapped as 'U':0, 'X':1, '0':2, '1':3
136 * 'Z':4, 'W':5, 'L':6, 'H':7, '-':8 . The std_logic_vector
137 * is stored as a contiguous array of bytes. For example
138 * "0101Z" is stored in five bytes as char s[5] = {2,3,2,3,4}
139 * An HDL integer type is stored as C int, a HDL real type is
140 * stored as a C double and a VHDL string type is stored as char*.
141 * An array of HDL integer or double is stored as an array of C
142 * integer or double respectively
143 */
144
145 /* In case you are not familiar with VHDL simulation, there are 9 possible
146 * values defined for the standard logic type, instead of just 0 and 1. The
147 * simulator needs to compute all these possible outcomes. Therefore, XSI uses
148 * a byte, instead of a bit, to represent a std_logic. This is represented
149 * with a char with possible values ranging from 0 to 8.
150 */
151 const char* std_logic_literal[] = {"U", "X", "0", "1", "Z", "W", "L", "H", "-"};
153 const char one_val = 3;
155 const char zero_val = 2;
156
157 char std_logic(bool inBit)
158 {
159 char outBit = zero_val;
160 if (inBit) {
161 outBit = one_val;
162 }
163 return outBit;
164 }
165
166 std::string display_value(const char* count, int size)
167 {
168 std::string res;
169 for (int i = 0; i < size; i++) {
170 if (count[i] >= 0 && count[i] < 9) {
171 res += std_logic_literal[(int) count[i]];
172 } else {
173 B2DEBUG(20, "invalid signal detected: " << static_cast<int>(count[i]));
174 res += "?";
175 }
176 }
177 return res;
178 }
179
180 template<size_t N>
181 std::string slv_to_bin_string(std::array<char, N> signal, bool padding = false)
182 {
183 int ini = padding ? 4 - signal.size() % 4 : 0;
184 std::string res(ini, '0');
185 for (auto const& bit : signal) {
186 if (bit >= 0 && bit < 9) {
187 res += std_logic_literal[(int) bit];
188 } else {
189 B2DEBUG(20, "invalid signal detected: " << static_cast<int>(bit));
190 res += "0";
191 }
192 }
193 return res;
194 }
195
196 template<size_t N>
197 void display_hex(const std::array<char, N>& signal)
198 {
199 std::ios oldState(nullptr);
200 oldState.copyfmt(std::cout);
201 if (std::any_of(signal.begin(), signal.end(), [](char i)
202 {return i != zero_val && i != one_val;})) {
203 B2DEBUG(20, "Some bit in the signal vector is neither 0 nor 1. \n" <<
204 "Displaying binary values instead.");
205 std::cout << slv_to_bin_string(signal) << std::endl;
206 } else {
207 std::string binString = slv_to_bin_string(signal, true);
208 std::cout << std::setfill('0');
209 for (unsigned i = 0; i < signal.size(); i += 4) {
210 std::bitset<4> set(binString.substr(i, 4));
211 std::cout << std::setw(1) << std::hex << set.to_ulong();
212 }
213 }
214 std::cout << "\n";
215 std::cout.copyfmt(oldState);
216 }
217
218 /* extract a subset of bitstring, like substring.
219 *
220 * In principle this can be done using only integer manipulations, but for the
221 * sake of simplicity, let's just cast them to string. Beware the endianness.
222 * 0 refer to the rightmost bit in std::bitset, but the leftmost bit in
223 * std::string
224 */
225 template<size_t nbits, size_t min, size_t max>
226 std::bitset < max - min + 1 > subset(std::bitset<nbits> set)
227 {
228 const size_t outWidth = max - min + 1;
229 std::string str = set.to_string();
230 return std::bitset<outWidth>(str.substr(nbits - max - 1, outWidth));
231 }
232
233
241 unsigned short globalSegmentID(unsigned short localID, unsigned short iSL)
242 {
243 auto itr = nWiresInSuperLayer.begin();
244 unsigned short globalID = std::accumulate(itr, itr + iSL, 0);
245 globalID += localID;
246 return globalID;
247 }
248
249 static const double realNaN = std::numeric_limits<double>::quiet_NaN();
250
251 using tsOut = std::array<unsigned, 4>;
252 using tsOutArray = std::array<tsOut, 5>;
255 TRG2DFinderTrack() : omega(realNaN), phi0(realNaN) {}
257 double omega;
259 double phi0;
261 tsOutArray ts;
262 // hw values of 2dtrack
263 int hwOmega{0};
264 int hwPhi0{0};
265 };
269 double z;
271 double theta;
273 unsigned sector;
275 std::array<float, 9> inputID;
276 std::array<int, 9> rawinputID;
278 std::array<float, 9> inputT;
279 std::array<int, 9> rawinputT;
281 std::array<float, 9> inputAlpha;
282 std::array<int, 9> rawinputAlpha;
284 std::array<tsOut, 9> ts;
286 int hwZ{0};
287 int hwTheta{0};
288 };
292 unsigned foundtime,
293 unsigned iTracker,
295 {
296 if (int(b2line.offset + foundtime) >= 0 &&
297 int(b2line.offset + foundtime) < bitsNN->getEntries()) {
298
299 NNBitStream* bitsn = (*bitsNN)[foundtime + b2line.offset];
300
301 if (int(slv_to_bin_string(bitsn->signal()[iTracker]).size()) >= (NN_WIDTH - b2line.start)) {
302 data = slv_to_bin_string(bitsn->signal()[iTracker]).substr(NN_WIDTH - 1 - b2line.end, b2line.end - b2line.start + 1);
303 } else {
304 data = "";
305 }
306 } else {
307 data = "";
308 }
309
310
311 name = b2line.name;
312 }
313 std::string data;
314 std::string name;
315 };
316
317 std::vector<bool> decodedriftthreshold(std::string p_driftthreshold)
318 {
319 std::vector<bool> res;
320 for (unsigned i = 0; i < p_driftthreshold.size(); ++i) {
321 if (p_driftthreshold.substr(i, 1) == "1") {
322 res.push_back(true);
323 } else if (p_driftthreshold.substr(i, 1) == "0") {
324 res.push_back(false);
325 } else {
326 B2WARNING("Invalid input in NNBitstream appending 'false'!");
327 res.push_back(false);
328 }
329 }
330 return res;
331 }
332 std::vector<bool> decodefoundoldtrack(std::string p_foundoldtrack)
333 {
334 std::vector<bool> res;
335 for (unsigned i = 0; i < p_foundoldtrack.size(); ++i) {
336 if (p_foundoldtrack.substr(i, 1) == "1") {
337 res.push_back(true);
338 } else if (p_foundoldtrack.substr(i, 1) == "0") {
339 res.push_back(false);
340 } else {
341 B2WARNING("Invalid input in NNBitstream appending 'false'!");
342 res.push_back(false);
343 }
344 }
345 return res;
346 }
347 bool decodevalstereobit(const std::string& p_valstereobit)
348 {
349 bool res;
350 if (p_valstereobit == "1") {
351 res = true;
352 } else if (p_valstereobit == "0") {
353 res = false;
354 } else {
355 B2WARNING("Invalid input in NNBitstream appending 'false'!");
356 res = false;
357 }
358 return res;
359 }
360 bool decodebool(const std::string& boolstring)
361 {
362 bool res;
363 if (boolstring == "1") {
364 res = true;
365 } else if (boolstring == "0") {
366 res = false;
367 } else {
368 B2WARNING("Invalid input in NNBitstream, appending 'false'!");
369 res = false;
370 }
371 return res;
372 }
384 unsigned TSIDInSL(unsigned tsIDInTracker, unsigned iSL, unsigned iTracker)
385 {
386 const unsigned nCellsInSL = nMergers[iSL] * nCellsInLayer;
387 // get global TS ID
388 unsigned iTS = tsIDInTracker + nCellsInSL * iTracker / nTrackers;
389 // periodic ID overflow when phi0 > 0 for the 4th tracker
390 if (iTS >= nCellsInSL) {
391 iTS -= nCellsInSL;
392 }
393 // ID in SL8 is shifted by 16
394 if (iSL == 8) {
395 if (iTS < 16) {
396 iTS += nCellsInSL;
397 }
398 iTS -= 16;
399 }
400 return iTS;
401 }
402
405 int mlp_bin_to_signed_int(std::string signal)
406 {
407 constexpr unsigned len = 13;
408 std::bitset<len> signal_bit(signal);
409 const unsigned shift = 16 - len;
410 // shift to 16 bits, cast it to signed 16-bit int, and shift it back
411 // thus the signed bit is preserved (when right-shifting)
412 int signal_out = (int16_t (signal_bit.to_ulong() << shift)) >> shift;
413 return signal_out;
414 }
419 int recalcETF(std::string driftinput, std::vector<unsigned> tsvector, CDCTriggerTrack* track)
420 {
421 //scale factor to get a value between -1 and 1
422 float scale = 1. / (1 << (driftinput.size() - 1) / 9);
423 int ret = 0;
424 bool stor = false;
425 // make a table, with <possible etf, how often it was calculated
426 // it is possible there are different event t0 used, if some value
427 // in the hw is kept longer than it should be
428 std::vector<std::vector<int>> table;
429 for (unsigned iSL = 0; iSL < 9; ++iSL) {
430 // getting the relative drift time in clock cycles (1cc ~ 2ns)
431 int reldt = static_cast<int>(fabs((mlp_bin_to_signed_int(driftinput.substr((8 - iSL) * driftinput.size() / 9,
432 driftinput.size() / 9)) * scale * 256)));
433 int tstime = static_cast<int>(tsvector[iSL]);
434 // we do not want SLs with no LR info or pts outside of the time window
435 if (reldt != 0 && reldt < 255) {
436 for (std::vector<int>& x : table) {
437 stor = false;
438 if (x[0] == tstime - reldt) {
439 x[1]++;
440 stor = true;
441 }
442 }
443 if (!stor) {table.push_back({tstime - reldt, 1});}
444 }
445
446 }
447 // now get the event t0 recalculated most often and return it in the end
448 int maxi = 0;
449 for (std::vector<int>& x : table) {
450 if (x[1] > maxi) {
451 ret = x[0];
452 maxi = x[1];
453 }
454 }
455 // if there is a "wrong" input in the hardware values, the corresponding error bit is set
456 if (table.size() > 1) {track->setQualityVector(128);}
457 return ret;
458
459 }
460
468 tsOut decodeTSHit(std::string tsIn)
469 {
470 constexpr unsigned lenID = 8;
471 constexpr unsigned lenPriorityTime = 9; //(twodcc.size() > 0) ? 13 : 9;
472 constexpr unsigned lenLR = 2;
473 constexpr unsigned lenPriorityPosition = 2;
474 constexpr std::array<unsigned, 4> tsLens = {
475 lenID, lenPriorityTime, lenLR, lenPriorityPosition
476 };
477 std::array<unsigned, 5> tsPos = { 0 };
478 std::partial_sum(tsLens.begin(), tsLens.end(), tsPos.begin() + 1);
479 tsOut tsOutput;
480 tsOutput[0] = std::bitset<tsLens[0]>(tsIn.substr(tsPos[0], tsLens[0])).to_ulong();
481 tsOutput[1] = std::bitset<tsLens[1]>(tsIn.substr(tsPos[1], tsLens[1])).to_ulong();
482 tsOutput[2] = std::bitset<tsLens[2]>(tsIn.substr(tsPos[2], tsLens[2])).to_ulong();
483 tsOutput[3] = std::bitset<tsLens[3]>(tsIn.substr(tsPos[3], tsLens[3])).to_ulong();
484 return tsOutput;
485 }
486 tsOut decodeTSHit_sim(std::string tsIn, std::string twodcc)
487 {
488 constexpr unsigned lenID = 8;
489 constexpr unsigned lenPriorityTime = 9; //(twodcc.size() > 0) ? 13 : 9;
490 constexpr unsigned lenLR = 2;
491 constexpr unsigned lenPriorityPosition = 2;
492 constexpr std::array<unsigned, 4> tsLens = {
493 lenID, lenPriorityTime, lenLR, lenPriorityPosition
494 };
495 std::string C = tsIn.substr(lenID + 5, 4);
496 std::string B = tsIn.substr(lenID, 5);
497 std::string Bp = twodcc.substr(4, 5);
498 std::string Ap = twodcc.substr(0, 4);
499 int pt;
500 std::string pts;
501 if (std::stoul(B, 0, 2) <= std::stoul(Bp, 0, 2)) {
502 pts = Ap + B + C;
503 } else {
504 B2DEBUG(14, "2DCC overflow detected!");
505 pts = std::bitset<4>(std::stoul(Ap, 0, 2) - 1).to_string() + B + C;
506 }
507 pt = std::stoul(pts, 0, 2);
508 std::array<unsigned, 5> tsPos = { 0 };
509 std::partial_sum(tsLens.begin(), tsLens.end(), tsPos.begin() + 1);
510 tsOut tsOutput;
511 tsOutput[0] = std::bitset<tsLens[0]>(tsIn.substr(tsPos[0], tsLens[0])).to_ulong();
512 tsOutput[1] = pt; // std::bitset<tsLens[1]>(tsIn.substr(tsPos[1], tsLens[1])).to_ulong();
513 tsOutput[2] = std::bitset<tsLens[2]>(tsIn.substr(tsPos[2], tsLens[2])).to_ulong();
514 tsOutput[3] = std::bitset<tsLens[3]>(tsIn.substr(tsPos[3], tsLens[3])).to_ulong();
515 return tsOutput;
516 }
517 tsOut decodeTSHit_ext(std::string tsIn, std::string expt)
518 {
519 constexpr unsigned lenID = 8;
520 constexpr unsigned lenPriorityTime = 9; //(twodcc.size() > 0) ? 13 : 9;
521 constexpr unsigned lenLR = 2;
522 constexpr unsigned lenPriorityPosition = 2;
523 constexpr std::array<unsigned, 4> tsLens = {
524 lenID, lenPriorityTime, lenLR, lenPriorityPosition
525 };
526 unsigned pt = std::stoul(expt, 0, 2);
527 std::array<unsigned, 5> tsPos = { 0 };
528 std::partial_sum(tsLens.begin(), tsLens.end(), tsPos.begin() + 1);
529 tsOut tsOutput;
530 tsOutput[0] = std::bitset<tsLens[0]>(tsIn.substr(tsPos[0], tsLens[0])).to_ulong();
531 tsOutput[1] = pt; //std::bitset<13>(expt).to_ulong();
532 tsOutput[2] = std::bitset<tsLens[2]>(tsIn.substr(tsPos[2], tsLens[2])).to_ulong();
533 tsOutput[3] = std::bitset<tsLens[3]>(tsIn.substr(tsPos[3], tsLens[3])).to_ulong();
534 return tsOutput;
535 }
536
546 TRG2DFinderTrack decode2DTrack(const std::string& p_charge __attribute__((unused)),
547 std::string p_omega,
548 std::string p_phi,
549 const std::string& p_ts0,
550 const std::string& p_ts2,
551 const std::string& p_ts4,
552 const std::string& p_ts6,
553 const std::string& p_ts8,
554 unsigned iTracker,
555 const std::string& p_2dcc,
556 bool sim13dt)
557 {
558//constexpr unsigned lenomega = p_omega.size();
559 unsigned shift = 16 - p_omega.size();
560 TRG2DFinderTrack trackout;
561 int omega = std::stoi(p_omega, 0, 2);
562 // shift omega to 16 bits, cast it to signed 16-bit int, and shift it back to 7 bits
563 // thus the signed bit is preserved (when right-shifting)
564 int omegafirm = (int16_t (omega << shift)) >> shift;
565 trackout.hwOmega = omegafirm;
566 //int omegafirm = (int16_t (omega.to_ulong() << shift)) >> shift;
567 // B field is 1.5T
568 const double BField = 1.5e-4; // why is it so small?
569 // omega in 1/cm
570 // omega = 1/R = c * B / pt
571 trackout.omega = Const::speedOfLight * BField / 0.3 / 34 * omegafirm;
572
573
574
575
576 int phi = std::stoi(p_phi, 0, 2);
577 trackout.hwPhi0 = phi;
578 // c.f. https://xwiki.desy.de/xwiki/bin/download/BI/Belle%20II%20Internal/Detector%20WebHome/Trigger%20WebHome/Sub-Trigger%20Systems/CDC%20Trigger/WebHome/output-def.pdf?rev=1.1
579 double globalPhi0 = pi() / 4 + pi() / 2 / 80 * (phi + 1) + pi() / 2 * iTracker; // see document above
580
581
582 trackout.ts[0] = (sim13dt) ? decodeTSHit_sim(p_ts0, p_2dcc) : decodeTSHit(p_ts0);
583 trackout.ts[1] = (sim13dt) ? decodeTSHit_sim(p_ts2, p_2dcc) : decodeTSHit(p_ts2);
584 trackout.ts[2] = (sim13dt) ? decodeTSHit_sim(p_ts4, p_2dcc) : decodeTSHit(p_ts4);
585 trackout.ts[3] = (sim13dt) ? decodeTSHit_sim(p_ts6, p_2dcc) : decodeTSHit(p_ts6);
586 trackout.ts[4] = (sim13dt) ? decodeTSHit_sim(p_ts8, p_2dcc) : decodeTSHit(p_ts8);
587 // rotate the tracks to the correct quadrant (iTracker)
588 if (globalPhi0 > pi() * 2) {
589 globalPhi0 -= pi() * 2;
590 }
591 trackout.phi0 = globalPhi0;
592 B2DEBUG(20, "Unpacking 2DTrack in Tracker: " << iTracker);
593 B2DEBUG(20, " Omega: " << std::to_string(omega) << ", Omegafirm: " << std::to_string(omegafirm) << ", converted to: " <<
594 std::to_string(trackout.omega));
595 B2DEBUG(20, " Phi: " << std::to_string(phi) << ", converted to: " << std::to_string(trackout.phi0));
596 return trackout;
597
598 }
599 TRG2DFinderTrack decode2DTrack(std::string trackIn, unsigned iTracker)
600 {
601 constexpr unsigned lenCharge = 2;
602 constexpr unsigned lenOmega = 7;
603 constexpr unsigned lenPhi0 = 7;
604 constexpr std::array<unsigned, 3> trackLens = {lenCharge, lenOmega, lenPhi0};
605 std::array<unsigned, 4> trackPos{ 0 };
606 std::partial_sum(trackLens.begin(), trackLens.end(), trackPos.begin() + 1);
607 const unsigned shift = 16 - lenOmega;
608 TRG2DFinderTrack trackOut;
609 std::bitset<trackLens[1]> omega(trackIn.substr(trackPos[1], trackLens[1]));
610 // shift omega to 16 bits, cast it to signed 16-bit int, and shift it back to 7 bits
611 // thus the signed bit is preserved (when right-shifting)
612 int omegaFirm = (int16_t (omega.to_ulong() << shift)) >> shift;
613 trackOut.hwOmega = omegaFirm;
614 // B field is 1.5T
615 const double BField = 1.5e-4;
616 // omega in 1/cm
617 // omega = 1/R = c * B / pt
618 // c.f. https://xwiki.desy.de/xwiki/bin/download/BI/Belle%20II%20Internal/Detector%20WebHome/Trigger%20WebHome/Sub-Trigger%20Systems/CDC%20Trigger/WebHome/output-def.pdf?rev=1.1
619 trackOut.omega = Const::speedOfLight * BField / 0.3 / 34 * omegaFirm;
620 int phi0 = std::bitset<trackLens[2]>(trackIn.substr(trackPos[2], trackLens[2])).to_ulong();
621 trackOut.hwPhi0 = phi0;
622 trackOut.phi0 = pi() / 4 + pi() / 2 / 80 * (phi0 + 1);
623 for (unsigned i = 0; i < 5; ++i) {
624 trackOut.ts[i] = decodeTSHit(trackIn.substr(trackPos.back() + i * lenTS, lenTS));
625 }
626
627 // rotate the tracks to the correct quadrant (iTracker)
628 double globalPhi0 = trackOut.phi0 + pi() / 2 * iTracker;
629 if (globalPhi0 > pi() * 2) {
630 globalPhi0 -= pi() * 2;
631 }
632 trackOut.phi0 = globalPhi0;
633 return trackOut;
634 }
635
644 TRGNeuroTrack decodeNNTrack(std::string p_mlpout_z,
645 std::string p_mlpout_theta,
646 std::string p_tsfsel,
647 std::string p_mlpin_alpha,
648 std::string p_mlpin_drifttime,
649 std::string p_mlpin_id,
650 std::string p_netsel,
651 const DBObjPtr<CDCTriggerNeuroConfig>& neurodb,
652 const std::string& p_2dcc,
653 bool sim13dt,
654 B2LDataField p_extendedpts)
655 {
656 // constexpr unsigned lenMLP = 13;
657 float scale_z = 1. / (1 << (p_mlpout_z.size() - 1));
658 float scale_theta = 1. / (1 << (p_mlpout_theta.size() - 1));
659 float scale_alpha = 1. / (1 << (p_mlpin_alpha.size() - 1) / 9);
660 float scale_drifttime = 1. / (1 << (p_mlpin_drifttime.size() - 1) / 9);
661 float scale_id = 1. / (1 << (p_mlpin_id.size() - 1) / 9);
662 TRGNeuroTrack foundTrack;
663 int theta_raw = mlp_bin_to_signed_int(p_mlpout_theta);
664 int z_raw = mlp_bin_to_signed_int(p_mlpout_z);
665 foundTrack.hwZ = z_raw;
666 foundTrack.hwTheta = theta_raw;
667 std::vector<float> unscaledT = neurodb->getMLPs()[0].unscaleTarget({(z_raw * scale_z), (theta_raw * scale_theta)});
668 foundTrack.z = unscaledT[0];
669 foundTrack.theta = unscaledT[1];
670 foundTrack.sector = std::stoi(p_netsel, 0, 2);
671 for (unsigned iSL = 0; iSL < 9; ++iSL) {
672 foundTrack.inputAlpha[iSL] =
673 mlp_bin_to_signed_int(p_mlpin_alpha.substr((8 - iSL) * p_mlpin_alpha.size() / 9, p_mlpin_alpha.size() / 9)) * scale_alpha;
674 foundTrack.inputT[iSL] =
675 mlp_bin_to_signed_int(p_mlpin_drifttime.substr((8 - iSL) * p_mlpin_drifttime.size() / 9,
676 p_mlpin_drifttime.size() / 9)) * scale_drifttime;
677 foundTrack.inputID[iSL] =
678 mlp_bin_to_signed_int(p_mlpin_id.substr((8 - iSL) * p_mlpin_drifttime.size() / 9, p_mlpin_drifttime.size() / 9)) * scale_id;
679 foundTrack.rawinputAlpha[iSL] = mlp_bin_to_signed_int(p_mlpin_alpha.substr((8 - iSL) * p_mlpin_alpha.size() / 9,
680 p_mlpin_alpha.size() / 9));
681 foundTrack.rawinputT[iSL] = mlp_bin_to_signed_int(p_mlpin_drifttime.substr((8 - iSL) * p_mlpin_drifttime.size() / 9,
682 p_mlpin_drifttime.size() / 9));
683 foundTrack.rawinputID[iSL] = mlp_bin_to_signed_int(p_mlpin_id.substr((8 - iSL) * p_mlpin_drifttime.size() / 9,
684 p_mlpin_drifttime.size() / 9));
685 if (sim13dt) {
686 foundTrack.ts[iSL] = decodeTSHit_sim(p_tsfsel.substr((8 - iSL) * lenTS, lenTS), p_2dcc);
687 } else {
688 if (p_extendedpts.name != "None") {
689 foundTrack.ts[iSL] = decodeTSHit_ext(p_tsfsel.substr((8 - iSL) * lenTS, lenTS), p_extendedpts.data.substr((8 - iSL) * 13, 13));
690 } else {
691 foundTrack.ts[iSL] = decodeTSHit(p_tsfsel.substr((8 - iSL) * lenTS, lenTS));
692 }
693 }
694 }
695 return foundTrack;
696 }
697 TRGNeuroTrack decodeNNTrack_old(std::string trackIn, std::string selectIn)
698 {
699 constexpr unsigned lenMLP = 13;
700 float scale = 1. / (1 << (lenMLP - 1));
701 TRGNeuroTrack foundTrack;
702 int theta_raw = mlp_bin_to_signed_int(trackIn.substr(1, lenMLP));
703 foundTrack.theta = theta_raw * scale * M_PI_2 + M_PI_2;
704 int z_raw = mlp_bin_to_signed_int(trackIn.substr(lenMLP + 1, lenMLP));
705 foundTrack.z = z_raw * scale * 50.;
706 foundTrack.sector = std::bitset<3>(trackIn.substr(2 * lenMLP + 1, 3)).to_ulong();
707 for (unsigned iSL = 0; iSL < 9; ++iSL) {
708 foundTrack.inputAlpha[iSL] =
709 mlp_bin_to_signed_int(selectIn.substr((2 + (8 - iSL)) * lenMLP + 4, lenMLP)) * scale;
710 foundTrack.inputT[iSL] =
711 mlp_bin_to_signed_int(selectIn.substr((11 + (8 - iSL)) * lenMLP + 4, lenMLP)) * scale;
712 foundTrack.inputID[iSL] =
713 mlp_bin_to_signed_int(selectIn.substr((20 + (8 - iSL)) * lenMLP + 4, lenMLP)) * scale;
714 foundTrack.ts[iSL] = // order: SL8, ..., SL0
715 decodeTSHit(selectIn.substr(29 * lenMLP + 4 + (8 - iSL) * lenTS, lenTS));
716 }
717 return foundTrack;
718 }
719
724 CDCTriggerSegmentHit* addTSHit(tsOut ts, unsigned iSL, unsigned iTracker,
725 StoreArray<CDCTriggerSegmentHit>* tsHits,
726 int foundTime = 0)
727 {
728 unsigned iTS = TSIDInSL(ts[0], iSL, iTracker);
729 // check if hit is already existing in datastore
730 CDCTriggerSegmentHit* hit = nullptr;
731 //for (int ihit = 0; ihit < tsHits->getEntries(); ++ihit) {
732 // CDCTriggerSegmentHit* compare = (*tsHits)[ihit];
733 // if (compare->getISuperLayer() == iSL &&
734 // compare->getIWireCenter() == iTS &&
735 // compare->getPriorityPosition() == ts[3] &&
736 // compare->getLeftRight() == ts[2] &&
737 // compare->priorityTime() == int(ts[1])) {
738 // hit = compare;
739 // break;
740 // }
741 //}
742// !hit is always true.
743// if (!hit) {
744 hit = tsHits->appendNew(iSL, iTS, ts[3], ts[2], ts[1], 0, foundTime, iTracker);
745 B2DEBUG(15, "make hit at SL " << iSL << " ID " << iTS << " clock " << foundTime << " iTracker " << iTracker);
746// }
747 return hit;
748 }
749
764 void decode2DOutput(short foundTime,
765 T2DOutputBitStream* bits,
766 StoreArray<CDCTriggerTrack>* storeTracks,
767 StoreArray<CDCTriggerFinderClone>* storeClones,
768 StoreArray<CDCTriggerSegmentHit>* tsHits)
769 {
770 const unsigned lenTrack = 121;
771 const unsigned oldTrackWidth = 6;
772 const unsigned foundWidth = 6;
773 std::array<int, 4> posTrack;
774 for (unsigned i = 0; i < posTrack.size(); ++i) {
775 posTrack[i] = oldTrackWidth + foundWidth + lenTrack * i;
776 }
777 for (unsigned iTracker = 0; iTracker < nTrackers; ++iTracker) {
778 const auto slv = bits->signal()[iTracker];
779 std::string strOutput = slv_to_bin_string(slv).
780 substr(clockCounterWidth, T2DOutputWidth - clockCounterWidth);
781 for (unsigned i = 0; i < nMax2DTracksPerClock; ++i) {
782 // The first 6 bits indicate whether a track is found or not
783 if (slv[clockCounterWidth + oldTrackWidth + i] == one_val) {
784 TRG2DFinderTrack trk = decode2DTrack(strOutput.substr(posTrack[i], lenTrack), iTracker);
785 B2DEBUG(15, "2DOut phi0:" << trk.phi0 << ", omega:" << trk.omega
786 << ", at clock " << foundTime << ", tracker " << iTracker);
787 CDCTriggerTrack* track =
788 storeTracks->appendNew(trk.phi0, trk.omega, 0., foundTime, iTracker);
789 CDCTriggerFinderClone* clone =
790 storeClones->appendNew(slv[clockCounterWidth + i] == one_val, iTracker);
791 clone->addRelationTo(track);
792 // TODO: dig out the TS hits in DataStore, and
793 // add relations to them.
794 // Otherwise, create a new TS hit object and add the relation.
795 // However, the fastest time would be lost in this case.
796 // Problem: there might be multiple TS hits with the same ID,
797 // so the foundTime needs to be aligned first in order to compare.
798 for (unsigned iAx = 0; iAx < nAxialTSF; ++iAx) {
799 const auto& ts = trk.ts[iAx];
800 if (ts[3] > 0) {
801 unsigned iTS = TSIDInSL(ts[0], 2 * iAx, iTracker);
802 CDCTriggerSegmentHit* hit =
803 tsHits->appendNew(2 * iAx, // super layer
804 iTS, // TS number in super layer
805 ts[3], // priority position
806 ts[2], // L/R
807 ts[1], // priority time
808 0, // fastest time (unknown)
809 // set to a clock definitely outside the time window to receive the TS from TSF,
810 // so it won't cause any confusion of the TS origin.
811 // what I want to is to set it to (200 + 2DmoduleID[0,1,2,3]),
812 // so one can distinguish in which 2D this track is found.
813 // foundTime); // found time (using the unpacked clock cycle)
814 2000 + iTracker * 100 + foundTime,
815 iTracker); // quadrant
816 track->addRelationTo(hit);
817 }
818 }
819 }
820 }
821 }
822 }
823
836 void decode2DInput(short foundTime,
837 std::array<int, 4> timeOffset,
838 TSFOutputBitStream* bits,
839 StoreArray<CDCTriggerSegmentHit>* tsHits)
840 {
841 // Get the input TS to 2D from the Bitstream
842 for (unsigned iAx = 0; iAx < nAxialTSF; ++iAx) {
843 for (unsigned iTracker = 0; iTracker < nTrackers; ++iTracker) {
844 const auto& tracker = bits->signal()[iAx][iTracker];
845 std::string strInput = slv_to_bin_string(tracker);
846 bool noMoreHit = false;
847 for (unsigned pos = clockCounterWidth; pos < TSFOutputWidth; pos += lenTS) {
848 std::string tsHitStr = strInput.substr(pos, lenTS);
849 B2DEBUG(50, tsHitStr);
850 tsOut ts = decodeTSHit(tsHitStr);
851 // check if all the hits are on the MSB side
852 if (ts[2] == 0) {
853 noMoreHit = true;
854 continue;
855 } else if (noMoreHit) {
856 B2DEBUG(20, "Discontinuous TS hit detected!");
857 }
858 unsigned iTS = TSIDInSL(ts[0], 2 * iAx, iTracker);
859 // Make TS hit object
860 CDCTriggerSegmentHit hit(2 * iAx, // super layer
861 iTS, // TS number in super layer
862 ts[3], // priority position
863 ts[2], // L/R
864 ts[1], // priority time
865 0, // fastest time (unknown)
866 foundTime + timeOffset[iTracker], // found time
867 iTracker); // quadrant
868
869 // add if the TS hit of identical ID and foundTime is not already in the StoreArray
870 // (from the 2D input of another quarter or the 2D track output)
871
872 /* TODO: Currently, it is very likely that a TS hit will appear
873 * multiple times in the StoreArray. To avoid adding the input from
874 * another quarter again, we need to look at the clock counter,
875 * because the data from different 2D's are not always synchronized
876 * due to Belle2Link instability. To avoid adding again from the 2D
877 * output, we need to consider the 2D latency.
878 */
879 if (std::none_of(tsHits->begin(), tsHits->end(),
880 [hit](CDCTriggerSegmentHit storeHit) {
881 return (storeHit.getSegmentID() == hit.getSegmentID() &&
882 storeHit.foundTime() == hit.foundTime());
883 })) {
884 B2DEBUG(40, "found TS hit ID " << hit.getSegmentID() <<
885 ", SL" << 2 * iAx << ", local ID " << iTS <<
886 ", 2D" << iTracker);
887 tsHits->appendNew(hit);
888 } else {
889 B2DEBUG(45, "skipping redundant hit ID " << hit.getSegmentID() << " in 2D" << iTracker);
890 }
891 }
892 }
893 }
894 }
895
912 CDCTriggerTrack* decodeNNInput(short iclock,
913 unsigned iTracker,
914 NNBitStream* bitsIn,
915 StoreArray<CDCTriggerTrack>* store2DTracks,
916 StoreArray<CDCTriggerSegmentHit>* tsHits)
917 {
918 CDCTriggerTrack* track2D = nullptr;
919 constexpr unsigned lenTrack = 135; //119;
920 // omega (7 bit) + phi (7 bit) + 5 * TS (21 bit) + old track found(6bit) + valid stereo bit (1bit) + drift threshold (9bit)
921 const auto slvIn = bitsIn->signal()[iTracker];
922 std::string strIn = slv_to_bin_string(slvIn);
923 strIn = strIn.substr(NN_WIDTH - 570 - 496, 982);
924 // decode stereo hits
925 for (unsigned iSt = 0; iSt < nStereoTSF; ++iSt) {
926 for (unsigned iHit = 0; iHit < 10; ++iHit) {
927 // order: 10 * SL7, 10 * SL5, 10 * SL3, 10 * SL1
928 unsigned pos = ((nStereoTSF - iSt - 1) * 10 + iHit) * lenTS;
929 tsOut ts = decodeTSHit(strIn.substr(pos, lenTS));
930 if (ts[3] > 0) {
931 addTSHit(ts, iSt * 2 + 1, iTracker, tsHits, iclock);
932 }
933 }
934 }
935 std::string strTrack = strIn.substr(nStereoTSF * 10 * lenTS, lenTrack);
936 if (!std::all_of(strTrack.begin(), strTrack.end(), [](char i) {return i == '0';})) {
937 std::string infobits = strTrack.substr(5 * lenTS + 14, 16);
938 strTrack = "00" + strTrack.substr(5 * lenTS, 14) + strTrack.substr(0,
939 5 * lenTS); // add 2 dummy bits for the charge (not stored in NN)
940 TRG2DFinderTrack trk2D = decode2DTrack(strTrack, iTracker);
941 B2DEBUG(15, "NNIn phi0:" << trk2D.phi0 << ", omega:" << trk2D.omega
942 << ", at clock " << iclock << ", tracker " << iTracker);
943 B2DEBUG(300, "Content of new infobits: " << infobits);
944 std::vector<bool> foundoldtrack;
945 std::vector<bool> driftthreshold;
946 bool valstereobit;
947 unsigned i = 0;
948 for (i = 0; i < 6; i++) {
949 if (infobits.substr(i, 1) == "1") {
950 foundoldtrack.push_back(true);
951 } else if (infobits.substr(i, 1) == "0") {
952 foundoldtrack.push_back(false);
953 } else {
954 B2WARNING("Invalid input in NNBitstream appending 'false'!");
955 foundoldtrack.push_back(false);
956 }
957 }
958 i = 6;
959 if (infobits.substr(i, 1) == "1") {
960 valstereobit = true;
961 } else if (infobits.substr(i, 1) == "0") {
962 valstereobit = false;
963 } else {
964 B2WARNING("Invalid input in NNBitstream appending 'false'!");
965 valstereobit = false;
966 }
967 for (i = 7; i < 16; i++) {
968 if (infobits.substr(i, 1) == "1") {
969 driftthreshold.push_back(true);
970 } else if (infobits.substr(i, 1) == "0") {
971 driftthreshold.push_back(false);
972 } else {
973 B2WARNING("Invalid input in NNBitstream appending 'false'!");
974 driftthreshold.push_back(false);
975 }
976 }
977 B2DEBUG(15, "bits for foundoldtrack: " << foundoldtrack[0]
978 << foundoldtrack[1]
979 << foundoldtrack[2]
980 << foundoldtrack[3]
981 << foundoldtrack[4]
982 << foundoldtrack[5]);
983 B2DEBUG(15, "bits for driftthreshold: " << driftthreshold[0]
984 << driftthreshold[1]
985 << driftthreshold[2]
986 << driftthreshold[3]
987 << driftthreshold[4]
988 << driftthreshold[5]
989 << driftthreshold[6]
990 << driftthreshold[7]
991 << driftthreshold[8]);
992 B2DEBUG(15, "bits for valstereobit: " << valstereobit);
993
994 // check if 2D track is already in list, otherwise add it
995 //for (int itrack = 0; itrack < store2DTracks->getEntries(); ++itrack) {
996 // if ((*store2DTracks)[itrack]->getPhi0() == trk2D->phi0 &&
997 // (*store2DTracks)[itrack]->getOmega() == trk2D->omega) {
998 // track2D = (*store2DTracks)[itrack];
999 // B2DEBUG(15, "found 2D track in store with phi " << trk2D->phi0 << " omega " << trk2D->omega);
1000 // break;
1001 // }
1002 //}
1003 B2DEBUG(15, "make new 2D track with phi " << trk2D.phi0 << " omega " << trk2D.omega << " clock " << iclock);
1004 track2D = store2DTracks->appendNew(trk2D.phi0, trk2D.omega, 0., foundoldtrack, driftthreshold, valstereobit, iclock, iTracker);
1005 // add axial hits and create relations
1006 for (unsigned iAx = 0; iAx < nAxialTSF; ++iAx) {
1007 const auto& ts = trk2D.ts[iAx];
1008 if (ts[3] > 0) {
1009 CDCTriggerSegmentHit* hit =
1010 addTSHit(ts, 2 * iAx, iTracker, tsHits, iclock);
1011 track2D->addRelationTo(hit);
1012 }
1013 }
1014 // TODO: decode event time
1015 }
1016 return track2D;
1017 }
1018
1039 void decodeNNOutput_old(short foundTime,
1040 unsigned iTracker,
1041 NNBitStream* bitsOut,
1042 NNBitStream* bitsSelectTS,
1043 StoreArray<CDCTriggerTrack>* storeNNTracks,
1044 StoreArray<CDCTriggerSegmentHit>* tsHits,
1045 StoreArray<CDCTriggerMLPInput>* storeNNInputs,
1046 CDCTriggerTrack* track2D)
1047 {
1048 const auto slvOut = bitsOut->signal()[iTracker];
1049 std::string strTrack = slv_to_bin_string(slvOut);
1050 strTrack = strTrack.substr(496, 570);
1051 const auto slvSelect = bitsSelectTS->signal()[iTracker];
1052 std::string strSelect = slv_to_bin_string(slvSelect);
1053 strSelect = strSelect.substr(496, 570);
1054 TRGNeuroTrack trkNN = decodeNNTrack_old(strTrack, strSelect);
1055 B2DEBUG(15, "make new NN track with , z:" << trkNN.z << ", theta:" << trkNN.theta <<
1056 ", sector:" << trkNN.sector << ", clock " << foundTime);
1057 double phi0 = 0;
1058 double omega = 0;
1059 if (track2D) {
1060 phi0 = track2D->getPhi0();
1061 omega = track2D->getOmega();
1062 }
1063 std::vector<unsigned> tsvector(9, 0);
1064 for (unsigned iSL = 0; iSL < 9; ++iSL) {
1065 tsvector[iSL] = trkNN.ts[iSL][2]; // save lr info in tsvector array
1066 }
1067 CDCTriggerTrack* trackNN = storeNNTracks->appendNew(phi0, omega, 0.,
1068 trkNN.z, cos(trkNN.theta) / sin(trkNN.theta), 0., track2D->getFoundOldTrack(), track2D->getDriftThreshold(),
1069 track2D->getValidStereoBit(), trkNN.sector, tsvector, foundTime, iTracker);
1070 std::vector<float> inputVector(27, 0.);
1071 for (unsigned iSL = 0; iSL < 9; ++iSL) {
1072 inputVector[3 * iSL] = trkNN.inputID[iSL];
1073 inputVector[3 * iSL + 1] = trkNN.inputT[iSL];
1074 inputVector[3 * iSL + 2] = trkNN.inputAlpha[iSL];
1075 }
1076 CDCTriggerMLPInput* storeInput =
1077 storeNNInputs->appendNew(inputVector, trkNN.sector);
1078 trackNN->addRelationTo(storeInput);
1079 track2D->addRelationTo(trackNN);
1080
1081 for (unsigned iSL = 0; iSL < 9; ++iSL) {
1082 if (trkNN.ts[iSL][3] > 0) {
1083 CDCTriggerSegmentHit* hit = addTSHit(trkNN.ts[iSL], iSL, iTracker, tsHits, foundTime);
1084 trackNN->addRelationTo(hit);
1085 }
1086 }
1087 }
1088
1106 void decodeNNIO(
1107 StoreArray<CDCTriggerUnpacker::NNBitStream>* bitsNN,
1108 StoreArray<CDCTriggerTrack>* store2DTracks,
1109 StoreArray<CDCTriggerTrack>* storeNNTracks,
1110 StoreArray<CDCTriggerSegmentHit>* tsHits,
1111 StoreArray<CDCTriggerSegmentHit>* tsHitsAll,
1112 StoreArray<CDCTriggerMLPInput>* storeNNInputs,
1113 StoreObjPtr<BinnedEventT0> storeETFTime,
1114 const DBObjPtr<CDCTriggerNeuroConfig> neurodb,
1115 bool sim13dt)
1116 {
1117 for (unsigned iTracker = 0; iTracker < nTrackers; ++iTracker) {
1118 B2DEBUG(21, "----------------------------------------------------------------------------------------------------");
1119 B2DEBUG(21, padright(" Unpacking Tracker: " + std::to_string(iTracker), 100));
1120 // loop over boards belonging to geometrical sectors
1121
1122 for (short iclock = 0; iclock < bitsNN->getEntries(); ++iclock) {
1123 // check for NNEnable bit:
1124 B2LDataField p_nnenable(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("NNEnable"));
1125 if (p_nnenable.name == "None") {
1126 B2DEBUG(5, "Neurotrigger: NNENable position unknown, skipping ... ");
1127 continue;
1128 } else if (p_nnenable.data == "1") {
1129 B2DEBUG(10, padright("Tracker: " + std::to_string(iTracker) + ", Clock: " + std::to_string(iclock) + " : NNEnable set!", 100));
1130 } else {
1131 B2DEBUG(21, padright(" UnpackerClock: " + std::to_string(iclock), 100));
1132 }
1133
1134
1135 CDCTriggerNeuroConfig::B2FormatLine nnall;
1136 nnall.start = 0;
1137 nnall.end = 2047;
1138 nnall.offset = 0;
1139 nnall.name = "nnall";
1140 B2LDataField p_nnall(bitsNN, iclock, iTracker, nnall);
1141 B2DEBUG(22, padright(" all bits: ", 100));
1142 B2DEBUG(22, padright(" " + p_nnall.data, 100));
1143 // define variables to fill from the bitstream, B2LDataField holds just the string, not the unpacked data yet
1144 B2LDataField p_driftthreshold(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("DriftThreshold"));
1145 if ((p_driftthreshold.name != "None") && (p_driftthreshold.data.size() == 0)) {
1146 B2DEBUG(10, "Could not load Datafield: " << p_driftthreshold.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1147 iclock);
1148 continue;
1149 }
1150
1151 B2LDataField p_valstereobit(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("ValStereoBit"));
1152 if ((p_valstereobit.name != "None") && (p_valstereobit.data.size() == 0)) {
1153 B2DEBUG(10, "Could not load Datafield: " << p_valstereobit.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1154 iclock);
1155 continue;
1156 }
1157
1158 B2LDataField p_foundoldtrack(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("FoundOldTrack"));
1159 if ((p_foundoldtrack.name != "None") && (p_foundoldtrack.data.size() == 0)) {
1160 B2DEBUG(10, "Could not load Datafield: " << p_foundoldtrack.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1161 iclock);
1162 continue;
1163 }
1164
1165 B2LDataField p_phi(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("Phi"));
1166 if ((p_phi.name != "None") && (p_phi.data.size() == 0)) {
1167 B2DEBUG(10, "Could not load Datafield: " << p_phi.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1168 continue;
1169 }
1170
1171 B2LDataField p_omega(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("Omega"));
1172 if ((p_omega.name != "None") && (p_omega.data.size() == 0)) {
1173 B2DEBUG(10, "Could not load Datafield: " << p_omega.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1174 continue;
1175 }
1176
1177 B2LDataField p_ts8(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS8"));
1178 if ((p_ts8.name != "None") && (p_ts8.data.size() == 0)) {
1179 B2DEBUG(10, "Could not load Datafield: " << p_ts8.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1180 continue;
1181 }
1182
1183 B2LDataField p_ts6(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS6"));
1184 if ((p_ts6.name != "None") && (p_ts6.data.size() == 0)) {
1185 B2DEBUG(10, "Could not load Datafield: " << p_ts6.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1186 continue;
1187 }
1188
1189 B2LDataField p_ts4(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS4"));
1190 if ((p_ts4.name != "None") && (p_ts4.data.size() == 0)) {
1191 B2DEBUG(10, "Could not load Datafield: " << p_ts4.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1192 continue;
1193 }
1194
1195 B2LDataField p_ts2(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS2"));
1196 if ((p_ts2.name != "None") && (p_ts2.data.size() == 0)) {
1197 B2DEBUG(10, "Could not load Datafield: " << p_ts2.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1198 continue;
1199 }
1200
1201 B2LDataField p_ts0(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS0"));
1202 if ((p_ts0.name != "None") && (p_ts0.data.size() == 0)) {
1203 B2DEBUG(10, "Could not load Datafield: " << p_ts0.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1204 continue;
1205 }
1206
1207 B2LDataField p_tsf1(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSF1"));
1208 if ((p_tsf1.name != "None") && (p_tsf1.data.size() == 0)) {
1209 B2DEBUG(10, "Could not load Datafield: " << p_tsf1.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1210 continue;
1211 }
1212
1213 B2LDataField p_tsf3(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSF3"));
1214 if ((p_tsf3.name != "None") && (p_tsf3.data.size() == 0)) {
1215 B2DEBUG(10, "Could not load Datafield: " << p_tsf3.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1216 continue;
1217 }
1218
1219 B2LDataField p_tsf5(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSF5"));
1220 if ((p_tsf5.name != "None") && (p_tsf5.data.size() == 0)) {
1221 B2DEBUG(10, "Could not load Datafield: " << p_tsf5.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1222 continue;
1223 }
1224
1225 B2LDataField p_tsf7(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSF7"));
1226 if ((p_tsf7.name != "None") && (p_tsf7.data.size() == 0)) {
1227 B2DEBUG(10, "Could not load Datafield: " << p_tsf7.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1228 continue;
1229 }
1230
1231 B2LDataField p_tsfsel(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSFsel"));
1232 if ((p_tsfsel.name != "None") && (p_tsfsel.data.size() == 0)) {
1233 B2DEBUG(10, "Could not load Datafield: " << p_tsfsel.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1234 continue;
1235 }
1236
1237 B2LDataField p_mlpin_alpha(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPIn_alpha"));
1238 if ((p_mlpin_alpha.name != "None") && (p_mlpin_alpha.data.size() == 0)) {
1239 B2DEBUG(10, "Could not load Datafield: " << p_mlpin_alpha.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1240 iclock);
1241 continue;
1242 }
1243
1244 B2LDataField p_mlpin_drifttime(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPIn_driftt"));
1245 if ((p_mlpin_drifttime.name != "None") && (p_mlpin_drifttime.data.size() == 0)) {
1246 B2DEBUG(10, "Could not load Datafield: " << p_mlpin_drifttime.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1247 iclock);
1248 continue;
1249 }
1250
1251 B2LDataField p_mlpin_id(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPIn_id"));
1252 if ((p_mlpin_id.name != "None") && (p_mlpin_id.data.size() == 0)) {
1253 B2DEBUG(10, "Could not load Datafield: " << p_mlpin_id.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1254 iclock);
1255 continue;
1256 }
1257
1258 B2LDataField p_netsel(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("Netsel"));
1259 if ((p_netsel.name != "None") && (p_netsel.data.size() == 0)) {
1260 B2DEBUG(10, "Could not load Datafield: " << p_netsel.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1261 continue;
1262 }
1263
1264 B2LDataField p_mlpout_z(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPOut_z"));
1265 if ((p_mlpout_z.name != "None") && (p_mlpout_z.data.size() == 0)) {
1266 B2DEBUG(10, "Could not load Datafield: " << p_mlpout_z.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1267 iclock);
1268 continue;
1269 }
1270
1271 B2LDataField p_mlpout_theta(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPOut_theta"));
1272 if ((p_mlpout_theta.name != "None") && (p_mlpout_theta.data.size() == 0)) {
1273 B2DEBUG(10, "Could not load Datafield: " << p_mlpout_theta.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1274 iclock);
1275 continue;
1276 }
1277
1278 B2LDataField p_2dcc(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("2dcc"));
1279 if ((p_2dcc.name != "None") && (p_2dcc.data.size() == 0)) {
1280 B2DEBUG(10, "Could not load Datafield: " << p_2dcc.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1281 continue;
1282 }
1283
1284 B2LDataField p_extendedpts(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("extendedPriorityTimes"));
1285 if ((p_extendedpts.name != "None") && (p_extendedpts.data.size() == 0)) {
1286 B2DEBUG(10, "Could not load Datafield: " << p_extendedpts.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1287 iclock);
1288 continue;
1289 }
1290 B2LDataField p_etftime(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etftime"));
1291 if ((p_etftime.name != "None") && (p_etftime.data.size() == 0)) {
1292 B2DEBUG(10, "Could not load Datafield: " << p_etftime.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1293 iclock);
1294 continue;
1295 }
1296 B2LDataField p_etfcc(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etfcc"));
1297 if ((p_etfcc.name != "None") && (p_etfcc.data.size() == 0)) {
1298 B2DEBUG(10, "Could not load Datafield: " << p_etfcc.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1299 iclock);
1300 continue;
1301 }
1302 B2LDataField p_etfqual(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etfquality"));
1303 if ((p_etfqual.name != "None") && (p_etfqual.data.size() == 0)) {
1304 B2DEBUG(10, "Could not load Datafield: " << p_etfqual.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1305 iclock);
1306 continue;
1307 }
1308 B2LDataField p_etfval(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etfvalid"));
1309 if ((p_etfval.name != "None") && (p_etfval.data.size() == 0)) {
1310 B2DEBUG(10, "Could not load Datafield: " << p_etfval.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1311 iclock);
1312 continue;
1313 }
1314 B2LDataField p_nntgdl(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("nntgdl"));
1315 if ((p_nntgdl.name != "None") && (p_nntgdl.data.size() == 0)) {
1316 B2DEBUG(10, "Could not load Datafield: " << p_nntgdl.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1317 iclock);
1318 continue;
1319 }
1320 B2LDataField p_sttgdl(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("sttgdl"));
1321 if ((p_sttgdl.name != "None") && (p_sttgdl.data.size() == 0)) {
1322 B2DEBUG(10, "Could not load Datafield: " << p_sttgdl.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1323 iclock);
1324 continue;
1325 }
1326
1327 // B2LDataField (bitsNN, iclock, iTracker, neurodb->getB2FormatLine(""));
1328
1329 CDCTriggerTrack* track2D = nullptr;
1330 // decode stereo hits
1331 if (true) { // (p_nnenable.data == "1") {
1332 unsigned sln = 0;
1333 B2DEBUG(21, padright(" Stereos: ", 100));
1334 for (auto stereolayer : {p_tsf1, p_tsf3, p_tsf5, p_tsf7}) {
1335 if (stereolayer.name == "None") {
1336 B2ERROR("Error in CDCTriggerNeuroConfig Payload, position of stereo tsf could not be found!");
1337 continue;
1338 }
1339 std::string tsstr = " | ";
1340 for (unsigned iHit = 0; iHit < 10; ++iHit) {
1341 tsOut ts = (sim13dt) ? decodeTSHit_sim(stereolayer.data.substr(iHit * lenTS, lenTS),
1342 p_2dcc.data) : decodeTSHit(stereolayer.data.substr(iHit * lenTS, lenTS));
1343 if (ts[3] > 0) { // if it is 0, it means 'no hit'
1344 unsigned iTS = TSIDInSL(ts[0], sln * 2 + 1, iTracker);
1345 tsstr += std::to_string(iTS) + ", " + std::to_string(ts[1]) + ", " + std::to_string(ts[2]) + ", " + std::to_string(ts[3]) + " | ";
1346 addTSHit(ts, sln * 2 + 1, iTracker, tsHitsAll, iclock);
1347 }
1348 }
1349 B2DEBUG(21, padright(" SL" + std::to_string(sln * 2 + 1) + tsstr, 100));
1350 ++sln;
1351 }
1352 }
1353 B2DEBUG(21, padright(" 2DCC: " + std::to_string(std::stoi(p_2dcc.data, 0, 2)) + ", (" + p_2dcc.data + ")", 100));
1354 B2DEBUG(21, padright(" ETFCC: " + std::to_string(std::stoi(p_etfcc.data, 0, 2)) + ", (" + p_etfcc.data + ")", 100));
1355 B2DEBUG(21, padright(" ETFVAL: " + std::to_string(std::stoi(p_etfval.data, 0, 2)) + ", (" + p_etfval.data + ")", 100));
1356 B2DEBUG(21, padright(" ETFT0: " + std::to_string(std::stoi(p_etftime.data, 0, 2)) + ", (" + p_etftime.data + ")", 100));
1357 B2DEBUG(21, padright(" ETFQuality: " + std::to_string(std::stoi(p_etfqual.data, 0, 2)) + ", (" + p_etfqual.data + ")", 100));
1358 if (p_nnenable.data == "1") {
1359 bool hasETFTime = false;
1360 if (p_etfval.data == "1") {
1361 storeETFTime->addBinnedEventT0(std::stoi(p_etftime.data, 0, 2), Const::CDC);
1362 hasETFTime = true;
1363 }
1364 std::vector<bool> foundoldtrack{false};
1365 std::vector<bool> driftthreshold{false};
1366 bool valstereobit;
1367 if (p_foundoldtrack.name != "None") {
1368 foundoldtrack = decodefoundoldtrack(p_foundoldtrack.data);
1369 }
1370 if (p_driftthreshold.name != "None") {
1371 driftthreshold = decodedriftthreshold(p_driftthreshold.data);
1372 }
1373 if (p_valstereobit.name != "None") {
1374 valstereobit = decodevalstereobit(p_valstereobit.data);
1375 }
1376
1377 if (std::all_of(p_phi.data.begin(), p_phi.data.end(), [](char i) {return i == 0;})) {
1378 B2ERROR("Empty Phi Value found for 2DTrack, should not happen!");
1379 continue;
1380 }
1381 TRG2DFinderTrack trk2D = decode2DTrack(
1382 "00", //charge
1383 p_omega.data,
1384 p_phi.data,
1385 p_ts0.data,
1386 p_ts2.data,
1387 p_ts4.data,
1388 p_ts6.data,
1389 p_ts8.data,
1390 iTracker,
1391 p_2dcc.data,
1392 sim13dt);
1393 track2D = store2DTracks->appendNew(trk2D.phi0, trk2D.omega, 0., foundoldtrack, driftthreshold, valstereobit, iclock, iTracker);
1394 track2D->setRawOmega(trk2D.hwOmega);
1395 track2D->setRawPhi0(trk2D.hwPhi0);
1396 B2DEBUG(12, padright(" 2DTrack: (phi=" + std::to_string(trk2D.phi0) + ", omega=" + std::to_string(
1397 trk2D.omega) + ", update=" + std::to_string(foundoldtrack[1]) + ")", 100));
1398
1399 // add axial hits and create relations
1400 std::string tsstr;
1401 for (unsigned iAx = 0; iAx < nAxialTSF; ++iAx) {
1402 const auto& ts = trk2D.ts[iAx];
1403 if (ts[3] > 0) {
1404 CDCTriggerSegmentHit* hit =
1405 addTSHit(ts, 2 * iAx, iTracker, tsHitsAll, iclock);
1406 unsigned iTS = TSIDInSL(ts[0], iAx * 2, iTracker);
1407 tsstr += "(SL" + std::to_string(iAx * 2) + ", " + std::to_string(iTS) + ", " + std::to_string(ts[1]) + ", " + std::to_string(
1408 ts[2]) + ", " + std::to_string(ts[3]) + "),";
1409 track2D->addRelationTo(hit);
1410 }
1411 }
1412 B2DEBUG(16, padright(" 2DTrack TS: " + tsstr, 100));
1413
1414
1415 if (track2D) {
1416 TRGNeuroTrack trkNN;
1417 trkNN = decodeNNTrack(p_mlpout_z.data,
1418 p_mlpout_theta.data,
1419 p_tsfsel.data,
1420 p_mlpin_alpha.data,
1421 p_mlpin_drifttime.data,
1422 p_mlpin_id.data,
1423 p_netsel.data,
1424 neurodb,
1425 p_2dcc.data,
1426 sim13dt,
1427 p_extendedpts);
1428
1429
1430 B2DEBUG(11, padright(" NNTrack: (z=" + std::to_string(trkNN.z) + ", theta=" + std::to_string(trkNN.theta) + ")", 100));
1431
1432 double phi0 = track2D->getPhi0();
1433 double omega = track2D->getOmega();
1434
1435 std::vector<unsigned> tsvector(9, 0);
1436 std::vector<unsigned> tstimevector(9, 0);
1437 tsstr = "";
1438 // turns false, as soon as there is a ts, which is not contained in the 2dfindertrack
1439 bool isin2d = true;
1440 for (unsigned iSL = 0; iSL < 9; ++iSL) {
1441 tsvector[iSL] = trkNN.ts[iSL][3];
1442 tstimevector[iSL] = trkNN.ts[iSL][1];
1443 if (trkNN.ts[iSL][3] > 0) {
1444 unsigned iTS = TSIDInSL(trkNN.ts[iSL][0], iSL, iTracker);
1445 tsstr += "(SL" + std::to_string(iSL) + ", " + std::to_string(iTS) + ", " + std::to_string(trkNN.ts[iSL][1]) + ", " + std::to_string(
1446 trkNN.ts[iSL][2]) + ", " + std::to_string(trkNN.ts[iSL][3]) + "),\n";
1447 // check, wether axials are a subset of 2dfinderTS:
1448 if (iSL % 2 == 0) {
1449 if (!(trk2D.ts[iSL / 2][0] == trkNN.ts[iSL][0] &&
1450 //trk2D.ts[iSL / 2][1] == trkNN.ts[iSL][1] &&
1451 trk2D.ts[iSL / 2][2] == trkNN.ts[iSL][2] &&
1452 trk2D.ts[iSL / 2][3] == trkNN.ts[iSL][3])) {
1453 isin2d = false;
1454 }
1455 }
1456
1457 } else {
1458 tsstr += "( - ),\n";
1459 }
1460 }
1461
1462 B2DEBUG(15, padright(" NNTrack TS: " + tsstr, 100));
1463
1464 CDCTriggerTrack* trackNN = storeNNTracks->appendNew(phi0, omega, 0.,
1465 trkNN.z, cos(trkNN.theta) / sin(trkNN.theta), 0., track2D->getFoundOldTrack(), track2D->getDriftThreshold(),
1466 track2D->getValidStereoBit(), trkNN.sector, tsvector, iclock, iTracker);
1467 trackNN->setHasETFTime(hasETFTime);
1468 track2D->setHasETFTime(hasETFTime);
1469 trackNN->setRawOmega(track2D->getRawOmega());
1470 trackNN->setRawPhi0(track2D->getRawPhi0());
1471 trackNN->setRawTheta(trkNN.hwTheta);
1472 trackNN->setRawZ(trkNN.hwZ);
1473 if (hasETFTime) {
1474 trackNN->setETF_unpacked(std::stoi(p_etftime.data, 0, 2));
1475 track2D->setETF_unpacked(std::stoi(p_etftime.data, 0, 2));
1476 }
1477 trackNN->setETF_recalced(recalcETF(p_mlpin_drifttime.data, tstimevector, trackNN));
1478 track2D->setETF_recalced(recalcETF(p_mlpin_drifttime.data, tstimevector, trackNN));
1479
1480 if (isin2d == false) {
1481 trackNN->setQualityVector(1);
1482 }
1483 std::vector<float> inputVector(27, 0.);
1484 std::vector<int> rawinputVector(27, 0.);
1485 for (unsigned iSL = 0; iSL < 9; ++iSL) {
1486 inputVector[3 * iSL] = trkNN.inputID[iSL];
1487 inputVector[3 * iSL + 1] = trkNN.inputT[iSL];
1488 inputVector[3 * iSL + 2] = trkNN.inputAlpha[iSL];
1489 rawinputVector[3 * iSL] = trkNN.rawinputID[iSL];
1490 rawinputVector[3 * iSL + 1] = trkNN.rawinputT[iSL];
1491 rawinputVector[3 * iSL + 2] = trkNN.rawinputAlpha[iSL];
1492 }
1493 trackNN->setRawInput(rawinputVector);
1494
1495 CDCTriggerMLPInput* storeInput =
1496 storeNNInputs->appendNew(inputVector, trkNN.sector);
1497 trackNN->addRelationTo(storeInput);
1498 track2D->addRelationTo(trackNN);
1499
1500 for (unsigned iSL = 0; iSL < 9; ++iSL) {
1501 if (trkNN.ts[iSL][3] > 0) {
1502 CDCTriggerSegmentHit* hit = nullptr;
1503 // if (sim13dt) {
1504 // // get extended priority time for stereos from the allstereots storearray
1505 // for (int ihit = 0; ihit<tsHitsAll->getEntries(); ++ihit) {
1506 // CDCTriggerSegmentHit* compare = (*tsHitsAll)[ihit];
1507 // if (compare->getISuperLayer() == iSL &&
1508 // compare->getIWireCenter() == TSIDInSL(trkNN.ts[iSL][0], iSL, iTracker) &&
1509 // compare->getPriorityPosition() == trkNN.ts[iSL][3] &&
1510 // compare->getLeftRight() == trkNN.ts[iSL][2] ) {
1511 // hit = compare;
1512 // }
1513 // }
1514 // if (!(!hit)) {
1515 // tsHits->appendNew(hit->getISuperLayer(), hit->getIWireCenter(), hit->getPriorityPosition(), hit->getLeftRight(), hit->priorityTime(), 0, hit->foundTime(), iTracker);
1516 // }
1517 // // get the extended pt for axials from the already existing 2d TS
1518 // for (int ihit = 0; ihit<tsHits->getEntries(); ++ihit) {
1519 // CDCTriggerSegmentHit* compare = (*tsHits)[ihit];
1520 // if (compare->getISuperLayer() == iSL &&
1521 // compare->getIWireCenter() == TSIDInSL(trkNN.ts[iSL][0], iSL, iTracker) &&
1522 // compare->getPriorityPosition() == trkNN.ts[iSL][3] &&
1523 // compare->getLeftRight() == trkNN.ts[iSL][2] ) {
1524 // hit = compare;
1525 // }
1526 // }
1527
1528 // }
1529
1530 // cppcheck-suppress knownConditionTrueFalse
1531 if (!hit) {
1532 hit = addTSHit(trkNN.ts[iSL], iSL, iTracker, tsHits, iclock);
1533 // B2DEBUG(1, "Hit with short drift time added, should not happen!");
1534 // }
1535 }
1536 trackNN->addRelationTo(hit);
1537 if (iSL % 2 == 0) {
1538 track2D->addRelationTo(hit);
1539 }
1540 }
1541 }
1542 if (p_nntgdl.name != "None") {
1543 bool dbool = decodebool(p_nntgdl.data);
1544 trackNN->setNNTToGDL(dbool);
1545 B2DEBUG(20, "NNT to GDL Bit decision for this track is: " << dbool);
1546 }
1547 if (p_sttgdl.name != "None") {
1548 bool dbool = decodebool(p_sttgdl.data);
1549 trackNN->setSTTToGDL(dbool);
1550 B2DEBUG(20, "STT to GDL Bit decision for this track is: " << dbool);
1551 }
1552
1553 }
1554
1555
1556 //
1557 // B2DEBUG(15, "bits for foundoldtrack: ");
1558 // for (auto x : foundoldtrack) {
1559 // B2DEBUG(15, x);
1560 // }
1561 // B2DEBUG(15, "bits for driftthreshold: ");
1562 // for (auto x : driftthreshold) {
1563 // B2DEBUG(15, x);
1564 // }
1565 // B2DEBUG(15, "bits for valstereobit: " << valstereobit);
1566 // B2DEBUG(15, "make new 2D track with phi " << trk2D.phi0 << " omega " << trk2D.omega << " clock " << iclock);
1567
1568 }
1569 }
1570 }
1571 }
1572
1573 void decodeNNIO_old(
1574 StoreArray<CDCTriggerUnpacker::NNBitStream>* bitsNN,
1575 StoreArray<CDCTriggerTrack>* store2DTracks,
1576 StoreArray<CDCTriggerTrack>* storeNNTracks,
1577 StoreArray<CDCTriggerSegmentHit>* tsHits,
1578 StoreArray<CDCTriggerMLPInput>* storeNNInputs)
1579 {
1580 for (short iclock = 0; iclock < bitsNN->getEntries(); ++iclock) {
1581 NNBitStream* bitsIn = (*bitsNN)[iclock];
1582 NNBitStream* bitsOutEnable = (*bitsNN)[iclock];
1583 for (unsigned iTracker = 0; iTracker < nTrackers; ++iTracker) {
1584 const auto slvOutEnable = bitsOutEnable->signal()[iTracker];
1585 const auto slvIn = bitsIn->signal()[iTracker];
1586 std::string stringOutEnable = slv_to_bin_string(slvOutEnable); //.substr(NN_OUT_WIDTH - 570, NN_OUT_WIDTH);
1587 std::string stringIn = slv_to_bin_string(slvIn); //.substr(NN_OUT_WIDTH - 570, NN_OUT_WIDTH);
1588 if (stringOutEnable.c_str()[0] == '1') {
1589 CDCTriggerTrack* nntrack2D = decodeNNInput(iclock, iTracker, bitsIn, store2DTracks, tsHits);
1590 if (nntrack2D) {
1591 int foundTime = iclock;
1592 if (foundTime < bitsNN->getEntries()) {
1593 NNBitStream* bitsOut = (*bitsNN)[foundTime];
1594 NNBitStream* bitsSelectTS = (*bitsNN)[iclock];
1595 decodeNNOutput_old(iclock, iTracker, bitsOut, bitsSelectTS,
1596 storeNNTracks, tsHits, storeNNInputs,
1597 nntrack2D);
1598 }
1599 }
1600 }
1601 }
1602 }
1603 }
1604 }
1606}
Class to hold one clock cycle of raw bit content.
Definition: Bitstream.h:54
const SignalBus & signal()
accessors
Definition: Bitstream.h:70
static const double speedOfLight
[cm/ns]
Definition: Const.h:695
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
Abstract base class for different kinds of events.
std::bitset< max - min+1 > subset(std::bitset< nbits > set)
extract a subset of bitstring, like substring.
Definition: Cosim.h:120
const char one_val
'1' in XSI VHDL simulation
Definition: Cosim.h:43
void display_hex(const std::array< char, N > &signal)
Display signal in hex.
Definition: Cosim.h:81
const char * std_logic_literal[]
In case you are not familiar with VHDL simulation, there are 9 possible values defined for the standa...
Definition: Cosim.h:40
std::string slv_to_bin_string(std::array< char, N > signal, bool padding=false)
Transform into string.
Definition: Cosim.h:64
std::string display_value(const char *count, int size)
Display value of the signal.
Definition: Cosim.h:48
const char zero_val
'0' in XSI VHDL simulation
Definition: Cosim.h:45
std::string name
name of information in B2link
int offset
offset of information in B2Link
tsOutArray ts
all TS of a 2D track
Definition: Unpacker.h:261
int hwZ
raw output values of hw network
Definition: Unpacker.h:286
std::array< float, 9 > inputT
input T list of a NN track
Definition: Unpacker.h:278
std::array< float, 9 > inputAlpha
input Alpha list of a NN track
Definition: Unpacker.h:281
unsigned sector
sector of a NN track
Definition: Unpacker.h:273
std::array< float, 9 > inputID
input ID list of a NN track
Definition: Unpacker.h:275
std::array< tsOut, 9 > ts
input TS list of a NN track
Definition: Unpacker.h:284
double theta
theta of a NN track
Definition: Unpacker.h:271