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 {
31
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 static constexpr unsigned lenSTS = 87; // ID (8 bit) + t (9 bit) + LR (2 bit) + priority (2 bit) + extraT 5*11 + pattern 11
49
50 static constexpr int nMax2DTracksPerClock = 4;
51
52 // bit width of the clock counter
53 static constexpr int clockCounterWidth = 9;
54
55 /* number of mergers in axial super layers */
56 static constexpr std::array<int, nAxialTSF> nAxialMergers = {10, 12, 16, 20, 24};
57 /* number of wires in a super layer*/
58 static constexpr std::array<int, 9> nWiresInSuperLayer = {
59 160, 160, 192, 224, 256, 288, 320, 352, 384
60 };
61 /* Number of wire/cells in a single layer per merger unit */
62 static constexpr int nCellsInLayer = 16;
63
64
65 // dataobjects
66 using TSFOutputVector = std::array<char, TSFOutputWidth>;
67 using TSFOutputArray = std::array<TSFOutputVector, nTrackers>;
68 using TSFOutputBus = std::array<TSFOutputArray, nAxialTSF>;
69 using TSFOutputBitStream = Bitstream<TSFOutputBus>;
70
71 using T2DOutputVector = std::array<char, T2DOutputWidth>;
72 using T2DOutputBus = std::array<T2DOutputVector, nTrackers>;
73 using T2DOutputBitStream = Bitstream<T2DOutputBus>;
74
75 using NNVector = std::array<char, NN_WIDTH>;
76 using NNBus = std::array<NNVector, nTrackers>;
77 using NNBitStream = Bitstream<NNBus>;
78
79 using DNNVector = std::array<char, DNN_WIDTH>;
80 using DNNBus = std::array<DNNVector, nTrackers>;
81 using DNNBitStream = Bitstream<DNNBus>;
82
83 // using NNInputVector = std::array<char, NNInputWidth>;
84 // using NNInputBus = std::array<NNInputVector, nTrackers>;
85 // using NNInputBitStream = Bitstream<NNInputBus>;
86
87 // using NNOutputVector = std::array<char, NNOutputWidth>;
88 // using NNOutputBus = std::array<NNOutputVector, nTrackers>;
89 // using NNOutputBitStream = Bitstream<NNOutputBus>;
90
91 // functions
92 std::string padto(std::string s, unsigned l)
93 {
94 if (s.size() < l) {
95 s.insert(s.begin(), l - s.size(), ' ');
96 }
97 return s;
98 }
99 std::string padright(std::string s, unsigned l)
100 {
101 if (s.size() < l) {
102 s.insert(s.end(), l - s.size(), ' ');
103 }
104 return s;
105 }
106
107 void printBuffer(int* buf, int nwords)
108 {
109 for (int j = 0; j < nwords; ++j) {
110 printf(" %.8x", buf[j]);
111 if ((j + 1) % 8 == 0) {
112 printf("\n");
113 }
114 }
115 printf("\n");
116 return;
117 };
118
119 std::string rawIntToAscii(int buf)
120 {
121 std::ostringstream firmwareTypeStream;
122 firmwareTypeStream << std::hex << buf;
123 std::string firmwareTypeHex(firmwareTypeStream.str());
124 std::string firmwareType(4, '0');
125 for (int i = 0; i < 4; i++) {
126 std::istringstream firmwareTypeIStream(firmwareTypeHex.substr(i * 2, 2));
127 int character;
128 firmwareTypeIStream >> std::hex >> character;
129 firmwareType[i] = character;
130 }
131 return firmwareType;
132 };
133
134 std::string rawIntToString(int buf)
135 {
136 std::ostringstream firmwareVersionStream;
137 firmwareVersionStream << std::hex << buf;
138 return firmwareVersionStream.str();
139 };
140
141 /* Note: VHDL std_logic value is stored in a byte (char). The
142 * 9 values are mapped as 'U':0, 'X':1, '0':2, '1':3
143 * 'Z':4, 'W':5, 'L':6, 'H':7, '-':8 . The std_logic_vector
144 * is stored as a contiguous array of bytes. For example
145 * "0101Z" is stored in five bytes as char s[5] = {2,3,2,3,4}
146 * An HDL integer type is stored as C int, a HDL real type is
147 * stored as a C double and a VHDL string type is stored as char*.
148 * An array of HDL integer or double is stored as an array of C
149 * integer or double respectively
150 */
151
152 /* In case you are not familiar with VHDL simulation, there are 9 possible
153 * values defined for the standard logic type, instead of just 0 and 1. The
154 * simulator needs to compute all these possible outcomes. Therefore, XSI uses
155 * a byte, instead of a bit, to represent a std_logic. This is represented
156 * with a char with possible values ranging from 0 to 8.
157 */
158 const char* std_logic_literal[] = {"U", "X", "0", "1", "Z", "W", "L", "H", "-"};
160 const char one_val = 3;
162 const char zero_val = 2;
163
164 char std_logic(bool inBit)
165 {
166 char outBit = zero_val;
167 if (inBit) {
168 outBit = one_val;
169 }
170 return outBit;
171 }
172
173 std::string display_value(const char* count, int size)
174 {
175 std::string res;
176 for (int i = 0; i < size; i++) {
177 if (count[i] >= 0 && count[i] < 9) {
178 res += std_logic_literal[(int) count[i]];
179 } else {
180 B2DEBUG(20, "invalid signal detected: " << static_cast<int>(count[i]));
181 res += "?";
182 }
183 }
184 return res;
185 }
186
187 template<size_t N>
188 std::string slv_to_bin_string(std::array<char, N> signal, bool padding = false)
189 {
190 int ini = padding ? 4 - signal.size() % 4 : 0;
191 std::string res(ini, '0');
192 for (auto const& bit : signal) {
193 if (bit >= 0 && bit < 9) {
194 res += std_logic_literal[(int) bit];
195 } else {
196 B2DEBUG(20, "invalid signal detected: " << static_cast<int>(bit));
197 res += "0";
198 }
199 }
200 return res;
201 }
202
203 template<size_t N>
204 void display_hex(const std::array<char, N>& signal)
205 {
206 std::ios oldState(nullptr);
207 oldState.copyfmt(std::cout);
208 if (std::any_of(signal.begin(), signal.end(), [](char i)
209 {return i != zero_val && i != one_val;})) {
210 B2DEBUG(20, "Some bit in the signal vector is neither 0 nor 1. \n" <<
211 "Displaying binary values instead.");
212 std::cout << slv_to_bin_string(signal) << std::endl;
213 } else {
214 std::string binString = slv_to_bin_string(signal, true);
215 std::cout << std::setfill('0');
216 for (unsigned i = 0; i < signal.size(); i += 4) {
217 std::bitset<4> set(binString.substr(i, 4));
218 std::cout << std::setw(1) << std::hex << set.to_ulong();
219 }
220 }
221 std::cout << "\n";
222 std::cout.copyfmt(oldState);
223 }
224
225 /* extract a subset of bitstring, like substring.
226 *
227 * In principle this can be done using only integer manipulations, but for the
228 * sake of simplicity, let's just cast them to string. Beware the endianness.
229 * 0 refer to the rightmost bit in std::bitset, but the leftmost bit in
230 * std::string
231 */
232 template<size_t nbits, size_t min, size_t max>
233 std::bitset < max - min + 1 > subset(std::bitset<nbits> set)
234 {
235 const size_t outWidth = max - min + 1;
236 std::string str = set.to_string();
237 return std::bitset<outWidth>(str.substr(nbits - max - 1, outWidth));
238 }
239
240
248 unsigned short globalSegmentID(unsigned short localID, unsigned short iSL)
249 {
250 auto itr = nWiresInSuperLayer.begin();
251 unsigned short globalID = std::accumulate(itr, itr + iSL, 0);
252 globalID += localID;
253 return globalID;
254 }
255
256 static const double realNaN = std::numeric_limits<double>::quiet_NaN();
257
258 using tsOut = std::array<unsigned, 4>;
259 using extraHitTimeOut = std::array<unsigned, 12>;
260
261 using tsOutArray = std::array<tsOut, 5>;
263 struct TRG2DFinderTrack {
264 TRG2DFinderTrack() : omega(realNaN), phi0(realNaN) {}
266 double omega;
268 double phi0;
270 tsOutArray ts;
272 int hwOmega{0};
273 int hwPhi0{0};
274 };
275
278 double z;
280 double theta;
282 unsigned sector;
284 double prob;
286 std::array<float, 9> inputID;
287 std::array<int, 9> rawinputID;
289 std::array<float, 9> inputT;
290 std::array<int, 9> rawinputT;
292 std::array<float, 9> inputAlpha;
293 std::array<int, 9> rawinputAlpha;
295 std::array<std::array<float, 11>, 4> inputExtraT;
296 std::array<std::array<float, 11>, 4> rawinputExtraT;
298 std::array<tsOut, 9> ts;
299 std::array<extraHitTimeOut, 9> TSExtraT;
301 int hwZ{0};
302 int hwTheta{0};
303 int hwProb{0};
304 };
305
306 struct B2LDataField_DNN {
307 B2LDataField_DNN(
309 unsigned foundtime,
310 unsigned iTracker,
312 {
313 if (int(b2line.offset + foundtime) >= 0 &&
314 int(b2line.offset + foundtime) < bitsNN->getEntries()) {
315
316 CDCTriggerUnpacker::DNNBitStream* bitsn = (*bitsNN)[foundtime + b2line.offset];
317
318 if (int(slv_to_bin_string(bitsn->signal()[iTracker]).size()) >= (DNN_WIDTH - b2line.start)) {
319 data = slv_to_bin_string(bitsn->signal()[iTracker]).substr(DNN_WIDTH - 1 - b2line.end, b2line.end - b2line.start + 1);
320 } else {
321 data = "";
322 }
323 } else {
324 data = "";
325 }
326
327
328 name = b2line.name;
329 }
330 std::string data;
331 std::string name;
332 };
333
334 struct B2LDataField {
335 B2LDataField(
337 unsigned foundtime,
338 unsigned iTracker,
340 {
341 if (int(b2line.offset + foundtime) >= 0 &&
342 int(b2line.offset + foundtime) < bitsNN->getEntries()) {
343
344 NNBitStream* bitsn = (*bitsNN)[foundtime + b2line.offset];
345
346 if (int(slv_to_bin_string(bitsn->signal()[iTracker]).size()) >= (NN_WIDTH - b2line.start)) {
347 data = slv_to_bin_string(bitsn->signal()[iTracker]).substr(NN_WIDTH - 1 - b2line.end, b2line.end - b2line.start + 1);
348 } else {
349 data = "";
350 }
351 } else {
352 data = "";
353 }
354 name = b2line.name;
355 }
356 std::string data;
357 std::string name;
358 };
359
360 std::vector<bool> decodedriftthreshold(std::string p_driftthreshold)
361 {
362 std::vector<bool> res;
363 for (unsigned i = 0; i < p_driftthreshold.size(); ++i) {
364 if (p_driftthreshold.substr(i, 1) == "1") {
365 res.push_back(true);
366 } else if (p_driftthreshold.substr(i, 1) == "0") {
367 res.push_back(false);
368 } else {
369 B2WARNING("Invalid input in NNBitstream appending 'false'!");
370 res.push_back(false);
371 }
372 }
373 return res;
374 }
375 std::vector<bool> decodefoundoldtrack(std::string p_foundoldtrack)
376 {
377 std::vector<bool> res;
378 for (unsigned i = 0; i < p_foundoldtrack.size(); ++i) {
379 if (p_foundoldtrack.substr(i, 1) == "1") {
380 res.push_back(true);
381 } else if (p_foundoldtrack.substr(i, 1) == "0") {
382 res.push_back(false);
383 } else {
384 B2WARNING("Invalid input in NNBitstream appending 'false'!");
385 res.push_back(false);
386 }
387 }
388 return res;
389 }
390 bool decodevalstereobit(const std::string& p_valstereobit)
391 {
392 bool res;
393 if (p_valstereobit == "1") {
394 res = true;
395 } else if (p_valstereobit == "0") {
396 res = false;
397 } else {
398 B2WARNING("Invalid input in NNBitstream appending 'false'!");
399 res = false;
400 }
401 return res;
402 }
403 bool decodebool(const std::string& boolstring)
404 {
405 bool res;
406 if (boolstring == "1") {
407 res = true;
408 } else if (boolstring == "0") {
409 res = false;
410 } else {
411 B2WARNING("Invalid input in NNBitstream, appending 'false'!");
412 res = false;
413 }
414 return res;
415 }
427 unsigned TSIDInSL(unsigned tsIDInTracker, unsigned iSL, unsigned iTracker)
428 {
429 const unsigned nCellsInSL = nMergers[iSL] * nCellsInLayer;
430 // get global TS ID
431 unsigned iTS = tsIDInTracker + nCellsInSL * iTracker / nTrackers;
432 // periodic ID overflow when phi0 > 0 for the 4th tracker
433 if (iTS >= nCellsInSL) {
434 iTS -= nCellsInSL;
435 }
436 // ID in SL8 is shifted by 16
437 if (iSL == 8) {
438 if (iTS < 16) {
439 iTS += nCellsInSL;
440 }
441 iTS -= 16;
442 }
443 return iTS;
444 }
445
448 int mlp_bin_to_signed_int(std::string signal)
449 {
450 constexpr unsigned len = 13;
451 std::bitset<len> signal_bit(signal);
452 const unsigned shift = 16 - len;
453 // shift to 16 bits, cast it to signed 16-bit int, and shift it back
454 // thus the signed bit is preserved (when right-shifting)
455 int signal_out = (int16_t (signal_bit.to_ulong() << shift)) >> shift;
456 return signal_out;
457 }
462 int recalcETF(std::string driftinput, std::vector<unsigned> tsvector, CDCTriggerTrack* track)
463 {
464 //scale factor to get a value between -1 and 1
465 float scale = 1. / (1 << (driftinput.size() - 1) / 9);
466 int ret = 0;
467 bool stor = false;
468 // make a table, with <possible etf, how often it was calculated
469 // it is possible there are different event t0 used, if some value
470 // in the hw is kept longer than it should be
471 std::vector<std::vector<int>> table;
472 for (unsigned iSL = 0; iSL < 9; ++iSL) {
473 // getting the relative drift time in clock cycles (1cc ~ 2ns)
474 int reldt = static_cast<int>(fabs((mlp_bin_to_signed_int(driftinput.substr((8 - iSL) * driftinput.size() / 9,
475 driftinput.size() / 9)) * scale * 256)));
476 int tstime = static_cast<int>(tsvector[iSL]);
477 // we do not want SLs with no LR info or pts outside of the time window
478 if (reldt != 0 && reldt < 255) {
479 for (std::vector<int>& x : table) {
480 stor = false;
481 if (x[0] == tstime - reldt) {
482 x[1]++;
483 stor = true;
484 }
485 }
486 if (!stor) {table.push_back({tstime - reldt, 1});}
487 }
488
489 }
490 // now get the event t0 recalculated most often and return it in the end
491 int maxi = 0;
492 for (std::vector<int>& x : table) {
493 if (x[1] > maxi) {
494 ret = x[0];
495 maxi = x[1];
496 }
497 }
498 // if there is a "wrong" input in the hardware values, the corresponding error bit is set
499 if (table.size() > 1) {track->setQualityVector(128);}
500 return ret;
501
502 }
503
511 tsOut decodeTSHit(std::string tsIn)
512 {
513 constexpr unsigned lenID = 8;
514 constexpr unsigned lenPriorityTime = 9; //(twodcc.size() > 0) ? 13 : 9;
515 constexpr unsigned lenLR = 2;
516 constexpr unsigned lenPriorityPosition = 2;
517 constexpr std::array<unsigned, 4> tsLens = {
518 lenID, lenPriorityTime, lenLR, lenPriorityPosition
519 };
520 std::array<unsigned, 5> tsPos = { 0 };
521 std::partial_sum(tsLens.begin(), tsLens.end(), tsPos.begin() + 1);
522 tsOut tsOutput;
523 tsOutput[0] = std::bitset<tsLens[0]>(tsIn.substr(tsPos[0], tsLens[0])).to_ulong();
524 tsOutput[1] = std::bitset<tsLens[1]>(tsIn.substr(tsPos[1], tsLens[1])).to_ulong();
525 tsOutput[2] = std::bitset<tsLens[2]>(tsIn.substr(tsPos[2], tsLens[2])).to_ulong();
526 tsOutput[3] = std::bitset<tsLens[3]>(tsIn.substr(tsPos[3], tsLens[3])).to_ulong();
527 return tsOutput;
528 }
529 tsOut decodeTSHit_sim(std::string tsIn, std::string twodcc)
530 {
531 constexpr unsigned lenID = 8;
532 constexpr unsigned lenPriorityTime = 9; //(twodcc.size() > 0) ? 13 : 9;
533 constexpr unsigned lenLR = 2;
534 constexpr unsigned lenPriorityPosition = 2;
535 constexpr std::array<unsigned, 4> tsLens = {
536 lenID, lenPriorityTime, lenLR, lenPriorityPosition
537 };
538 std::string C = tsIn.substr(lenID + 5, 4);
539 std::string B = tsIn.substr(lenID, 5);
540 std::string Bp = twodcc.substr(4, 5);
541 std::string Ap = twodcc.substr(0, 4);
542 int pt;
543 std::string pts;
544 if (std::stoul(B, 0, 2) <= std::stoul(Bp, 0, 2)) {
545 pts = Ap + B + C;
546 } else {
547 B2DEBUG(14, "2DCC overflow detected!");
548 pts = std::bitset<4>(std::stoul(Ap, 0, 2) - 1).to_string() + B + C;
549 }
550 pt = std::stoul(pts, 0, 2);
551 std::array<unsigned, 5> tsPos = { 0 };
552 std::partial_sum(tsLens.begin(), tsLens.end(), tsPos.begin() + 1);
553 tsOut tsOutput;
554 tsOutput[0] = std::bitset<tsLens[0]>(tsIn.substr(tsPos[0], tsLens[0])).to_ulong();
555 tsOutput[1] = pt; // std::bitset<tsLens[1]>(tsIn.substr(tsPos[1], tsLens[1])).to_ulong();
556 tsOutput[2] = std::bitset<tsLens[2]>(tsIn.substr(tsPos[2], tsLens[2])).to_ulong();
557 tsOutput[3] = std::bitset<tsLens[3]>(tsIn.substr(tsPos[3], tsLens[3])).to_ulong();
558 return tsOutput;
559 }
560 extraHitTimeOut decodeTSHitExtra_sim(std::string tsIn, std::string twodcc)
561 {
562 constexpr unsigned extraDrift = 5;
563 constexpr unsigned offset = 32;
564 extraHitTimeOut etimeout;
565 etimeout[0] = std::bitset<11>(tsIn.substr(offset - 11, 11)).to_ulong();
566 std::string Bp = twodcc.substr(4, 5);
567 std::string Ap = twodcc.substr(0, 4);
568 for (int i = 0; i < 11; i++) {
569 std::string B = tsIn.substr(offset + extraDrift * i, extraDrift);
570 std::string C = "0000";
571 int pt;
572 std::string pts;
573 if (std::stoul(B, 0, 2) <= std::stoul(Bp, 0, 2)) {
574 pts = Ap + B + C;
575 } else {
576 B2DEBUG(14, "2DCC overflow detected!");
577 pts = std::bitset<4>(std::stoul(Ap, 0, 2) - 1).to_string() + B + C;
578 }
579 pt = std::stoul(pts, 0, 2);
580 etimeout[i + 1] = pt;
581 }
582 return etimeout;
583 }
584
585 extraHitTimeOut decodeTSHitExtra(std::string tsIn)
586 {
587 constexpr unsigned extraDrift = 5;
588 constexpr unsigned offset = 32;
589 std::string C = "0000";
590 extraHitTimeOut etimeout;
591 etimeout[0] = std::bitset<11>(tsIn.substr(offset - 11, 11)).to_ulong();
592 for (int i = 0; i < 11; i++) {
593 std::string B = tsIn.substr(offset + extraDrift * i, extraDrift);
594 etimeout[i] = std::stoul(B + C, 0, 2);
595 }
596 return etimeout;
597 }
598
599 tsOut decodeTSHit_ext(std::string tsIn, std::string expt)
600 {
601 constexpr unsigned lenID = 8;
602 constexpr unsigned lenPriorityTime = 9; //(twodcc.size() > 0) ? 13 : 9;
603 constexpr unsigned lenLR = 2;
604 constexpr unsigned lenPriorityPosition = 2;
605 constexpr std::array<unsigned, 4> tsLens = {
606 lenID, lenPriorityTime, lenLR, lenPriorityPosition
607 };
608 unsigned pt = std::stoul(expt, 0, 2);
609 std::array<unsigned, 5> tsPos = { 0 };
610 std::partial_sum(tsLens.begin(), tsLens.end(), tsPos.begin() + 1);
611 tsOut tsOutput;
612 tsOutput[0] = std::bitset<tsLens[0]>(tsIn.substr(tsPos[0], tsLens[0])).to_ulong();
613 tsOutput[1] = pt; //std::bitset<13>(expt).to_ulong();
614 tsOutput[2] = std::bitset<tsLens[2]>(tsIn.substr(tsPos[2], tsLens[2])).to_ulong();
615 tsOutput[3] = std::bitset<tsLens[3]>(tsIn.substr(tsPos[3], tsLens[3])).to_ulong();
616 return tsOutput;
617 }
618
628 TRG2DFinderTrack decode2DTrack(const std::string& p_charge __attribute__((unused)),
629 std::string p_omega,
630 std::string p_phi,
631 const std::string& p_ts0,
632 const std::string& p_ts2,
633 const std::string& p_ts4,
634 const std::string& p_ts6,
635 const std::string& p_ts8,
636 unsigned iTracker,
637 const std::string& p_2dcc,
638 bool sim13dt)
639 {
640//constexpr unsigned lenomega = p_omega.size();
641 unsigned shift = 16 - p_omega.size();
642 TRG2DFinderTrack trackout;
643 int omega = std::stoi(p_omega, 0, 2);
644 // shift omega to 16 bits, cast it to signed 16-bit int, and shift it back to 7 bits
645 // thus the signed bit is preserved (when right-shifting)
646 int omegafirm = (int16_t (omega << shift)) >> shift;
647 trackout.hwOmega = omegafirm;
648 //int omegafirm = (int16_t (omega.to_ulong() << shift)) >> shift;
649 // B field is 1.5T
650 const double BField = 1.5e-4; // why is it so small?
651 // omega in 1/cm
652 // omega = 1/R = c * B / pt
653 trackout.omega = Const::speedOfLight * BField / 0.3 / 34 * omegafirm;
654
655
656
657
658 int phi = std::stoi(p_phi, 0, 2);
659 trackout.hwPhi0 = phi;
660 // 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
661 double globalPhi0 = pi() / 4 + pi() / 2 / 80 * (phi + 1) + pi() / 2 * iTracker; // see document above
662
663
664 trackout.ts[0] = (sim13dt) ? decodeTSHit_sim(p_ts0, p_2dcc) : decodeTSHit(p_ts0);
665 trackout.ts[1] = (sim13dt) ? decodeTSHit_sim(p_ts2, p_2dcc) : decodeTSHit(p_ts2);
666 trackout.ts[2] = (sim13dt) ? decodeTSHit_sim(p_ts4, p_2dcc) : decodeTSHit(p_ts4);
667 trackout.ts[3] = (sim13dt) ? decodeTSHit_sim(p_ts6, p_2dcc) : decodeTSHit(p_ts6);
668 trackout.ts[4] = (sim13dt) ? decodeTSHit_sim(p_ts8, p_2dcc) : decodeTSHit(p_ts8);
669 // rotate the tracks to the correct quadrant (iTracker)
670 if (globalPhi0 > pi() * 2) {
671 globalPhi0 -= pi() * 2;
672 }
673 trackout.phi0 = globalPhi0;
674 B2DEBUG(20, "Unpacking 2DTrack in Tracker: " << iTracker);
675 B2DEBUG(20, " Omega: " << std::to_string(omega) << ", Omegafirm: " << std::to_string(omegafirm) << ", converted to: " <<
676 std::to_string(trackout.omega));
677 B2DEBUG(20, " Phi: " << std::to_string(phi) << ", converted to: " << std::to_string(trackout.phi0));
678 return trackout;
679
680 }
681 TRG2DFinderTrack decode2DTrack(std::string trackIn, unsigned iTracker)
682 {
683 constexpr unsigned lenCharge = 2;
684 constexpr unsigned lenOmega = 7;
685 constexpr unsigned lenPhi0 = 7;
686 constexpr std::array<unsigned, 3> trackLens = {lenCharge, lenOmega, lenPhi0};
687 std::array<unsigned, 4> trackPos{ 0 };
688 std::partial_sum(trackLens.begin(), trackLens.end(), trackPos.begin() + 1);
689 const unsigned shift = 16 - lenOmega;
690 TRG2DFinderTrack trackOut;
691 std::bitset<trackLens[1]> omega(trackIn.substr(trackPos[1], trackLens[1]));
692 // shift omega to 16 bits, cast it to signed 16-bit int, and shift it back to 7 bits
693 // thus the signed bit is preserved (when right-shifting)
694 int omegaFirm = (int16_t (omega.to_ulong() << shift)) >> shift;
695 trackOut.hwOmega = omegaFirm;
696 // B field is 1.5T
697 const double BField = 1.5e-4;
698 // omega in 1/cm
699 // omega = 1/R = c * B / pt
700 // 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
701 trackOut.omega = Const::speedOfLight * BField / 0.3 / 34 * omegaFirm;
702 int phi0 = std::bitset<trackLens[2]>(trackIn.substr(trackPos[2], trackLens[2])).to_ulong();
703 trackOut.hwPhi0 = phi0;
704 trackOut.phi0 = pi() / 4 + pi() / 2 / 80 * (phi0 + 1);
705 for (unsigned i = 0; i < 5; ++i) {
706 trackOut.ts[i] = decodeTSHit(trackIn.substr(trackPos.back() + i * lenTS, lenTS));
707 }
708
709 // rotate the tracks to the correct quadrant (iTracker)
710 double globalPhi0 = trackOut.phi0 + pi() / 2 * iTracker;
711 if (globalPhi0 > pi() * 2) {
712 globalPhi0 -= pi() * 2;
713 }
714 trackOut.phi0 = globalPhi0;
715 return trackOut;
716 }
717
726 TRGNeuroTrack decodeNNTrack(std::string p_mlpout_z,
727 std::string p_mlpout_theta,
728 std::string p_tsfsel,
729 std::string p_mlpin_alpha,
730 std::string p_mlpin_drifttime,
731 std::string p_mlpin_id,
732 std::string p_netsel,
733 const DBObjPtr<CDCTriggerNeuroConfig>& neurodb,
734 const std::string& p_2dcc,
735 bool sim13dt,
736 B2LDataField p_extendedpts)
737 {
738 // constexpr unsigned lenMLP = 13;
739 float scale_z = 1. / (1 << (p_mlpout_z.size() - 1));
740 float scale_theta = 1. / (1 << (p_mlpout_theta.size() - 1));
741 float scale_alpha = 1. / (1 << (p_mlpin_alpha.size() - 1) / 9);
742 float scale_drifttime = 1. / (1 << (p_mlpin_drifttime.size() - 1) / 9);
743 float scale_id = 1. / (1 << (p_mlpin_id.size() - 1) / 9);
744 TRGNeuroTrack foundTrack;
745 int theta_raw = mlp_bin_to_signed_int(p_mlpout_theta);
746 int z_raw = mlp_bin_to_signed_int(p_mlpout_z);
747 foundTrack.hwZ = z_raw;
748 foundTrack.hwTheta = theta_raw;
749 std::vector<float> unscaledT = neurodb->getMLPs()[0].unscaleTarget({(z_raw * scale_z), (theta_raw * scale_theta)});
750 foundTrack.z = unscaledT[0];
751 foundTrack.theta = unscaledT[1];
752 foundTrack.sector = std::stoi(p_netsel, 0, 2);
753 for (unsigned iSL = 0; iSL < 9; ++iSL) {
754 foundTrack.inputAlpha[iSL] =
755 mlp_bin_to_signed_int(p_mlpin_alpha.substr((8 - iSL) * p_mlpin_alpha.size() / 9, p_mlpin_alpha.size() / 9)) * scale_alpha;
756 foundTrack.inputT[iSL] =
757 mlp_bin_to_signed_int(p_mlpin_drifttime.substr((8 - iSL) * p_mlpin_drifttime.size() / 9,
758 p_mlpin_drifttime.size() / 9)) * scale_drifttime;
759 foundTrack.inputID[iSL] =
760 mlp_bin_to_signed_int(p_mlpin_id.substr((8 - iSL) * p_mlpin_drifttime.size() / 9, p_mlpin_drifttime.size() / 9)) * scale_id;
761 foundTrack.rawinputAlpha[iSL] = mlp_bin_to_signed_int(p_mlpin_alpha.substr((8 - iSL) * p_mlpin_alpha.size() / 9,
762 p_mlpin_alpha.size() / 9));
763 foundTrack.rawinputT[iSL] = mlp_bin_to_signed_int(p_mlpin_drifttime.substr((8 - iSL) * p_mlpin_drifttime.size() / 9,
764 p_mlpin_drifttime.size() / 9));
765 foundTrack.rawinputID[iSL] = mlp_bin_to_signed_int(p_mlpin_id.substr((8 - iSL) * p_mlpin_drifttime.size() / 9,
766 p_mlpin_drifttime.size() / 9));
767 if (sim13dt) {
768 foundTrack.ts[iSL] = decodeTSHit_sim(p_tsfsel.substr((8 - iSL) * lenTS, lenTS), p_2dcc);
769 } else {
770 if (p_extendedpts.name != "None") {
771 foundTrack.ts[iSL] = decodeTSHit_ext(p_tsfsel.substr((8 - iSL) * lenTS, lenTS), p_extendedpts.data.substr((8 - iSL) * 13, 13));
772 } else {
773 foundTrack.ts[iSL] = decodeTSHit(p_tsfsel.substr((8 - iSL) * lenTS, lenTS));
774 }
775 }
776 }
777 return foundTrack;
778 }
779
780
781
790 TRGNeuroTrack decodeDNNTrack(std::string p_mlpout_z,
791 std::string p_mlpout_theta,
792 std::string p_mlpout_prob,
793 std::string p_tsfsel,
794 std::string p_mlpin_alpha,
795 std::string p_mlpin_drifttime,
796 std::string p_mlpin_id,
797 std::string p_mlpin_extratime,
798 std::string p_netsel,
799 const DBObjPtr<CDCTriggerNeuroConfig>& neurodb,
800 const std::string& p_2dcc,
801 bool sim13dt,
802 B2LDataField_DNN p_extendedpts)
803 {
804 // constexpr unsigned lenMLP = 13;
805 float scale_z = 1. / (1 << (p_mlpout_z.size() - 1));
806 float scale_theta = 1. / (1 << (p_mlpout_theta.size() - 1));
807 float scale_prob = 1. / (1 << (p_mlpout_prob.size() - 1));
808 float scale_alpha = 1. / (1 << (p_mlpin_alpha.size() - 1) / 9);
809 float scale_drifttime = 1. / (1 << (p_mlpin_drifttime.size() - 1) / 9);
810 float scale_id = 1. / (1 << (p_mlpin_id.size() - 1) / 9);
811 float scale_extratime = 1. / (1 << (p_mlpin_extratime.size() - 1) / 44);
812 TRGNeuroTrack foundTrack;
813 int theta_raw = mlp_bin_to_signed_int(p_mlpout_theta);
814 int z_raw = mlp_bin_to_signed_int(p_mlpout_z);
815 int prob_raw = mlp_bin_to_signed_int(p_mlpout_prob);
816 //std::cout<<scale_prob<<" sclae p :: raw "<<prob_raw<<" output "<<p_mlpout_prob<<std::endl;
817 //std::cout<<scale_z<<" sclae z :: raw "<<z_raw<<" output "<<z_raw * scale_z<<std::endl;
818 foundTrack.hwZ = z_raw;
819 foundTrack.hwTheta = theta_raw;
820 foundTrack.hwProb = prob_raw;
821 std::vector<float> unscaledT = neurodb->getMLPs()[0].unscaleTarget({(z_raw * scale_z), (theta_raw * scale_theta)});
822 foundTrack.z = unscaledT[0];
823 foundTrack.theta = unscaledT[1];
824 //std::cout << scale_theta << " sclae theta :: raw " << theta_raw << " output " << unscaledT[1] << std::endl;
825 foundTrack.prob = prob_raw * scale_prob;
826 foundTrack.sector = std::stoi(p_netsel, 0, 2);
827 for (unsigned iSL = 0; iSL < 9; ++iSL) {
828 foundTrack.inputAlpha[iSL] =
829 mlp_bin_to_signed_int(p_mlpin_alpha.substr((8 - iSL) * p_mlpin_alpha.size() / 9, p_mlpin_alpha.size() / 9)) * scale_alpha;
830 foundTrack.inputT[iSL] =
831 mlp_bin_to_signed_int(p_mlpin_drifttime.substr((8 - iSL) * p_mlpin_drifttime.size() / 9,
832 p_mlpin_drifttime.size() / 9)) * scale_drifttime;
833 foundTrack.inputID[iSL] =
834 mlp_bin_to_signed_int(p_mlpin_id.substr((8 - iSL) * p_mlpin_drifttime.size() / 9, p_mlpin_drifttime.size() / 9)) * scale_id;
835 foundTrack.rawinputAlpha[iSL] = mlp_bin_to_signed_int(p_mlpin_alpha.substr((8 - iSL) * p_mlpin_alpha.size() / 9,
836 p_mlpin_alpha.size() / 9));
837 foundTrack.rawinputT[iSL] = mlp_bin_to_signed_int(p_mlpin_drifttime.substr((8 - iSL) * p_mlpin_drifttime.size() / 9,
838 p_mlpin_drifttime.size() / 9));
839 foundTrack.rawinputID[iSL] = mlp_bin_to_signed_int(p_mlpin_id.substr((8 - iSL) * p_mlpin_drifttime.size() / 9,
840 p_mlpin_drifttime.size() / 9));
841 if (sim13dt) {
842 foundTrack.ts[iSL] = decodeTSHit_sim(p_tsfsel.substr((8 - iSL) * lenSTS, lenSTS), p_2dcc);
843 } else {
844 if (p_extendedpts.name != "None") {
845 foundTrack.ts[iSL] = decodeTSHit_ext(p_tsfsel.substr((8 - iSL) * lenSTS, lenSTS), p_extendedpts.data.substr((8 - iSL) * 13, 13));
846 } else {
847 foundTrack.ts[iSL] = decodeTSHit(p_tsfsel.substr((8 - iSL) * lenSTS, lenSTS));
848 }
849 }
850
851 if (p_tsfsel.size() % 87 == 0) {
852 foundTrack.TSExtraT[iSL] = sim13dt ? decodeTSHitExtra_sim(p_tsfsel.substr((8 - iSL) * lenSTS, lenSTS),
853 p_2dcc) : decodeTSHitExtra(p_tsfsel.substr((8 - iSL) * lenSTS, lenSTS));
854 } else {
855 foundTrack.TSExtraT[iSL] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
856 }
857 }
858 for (unsigned iSL = 0; iSL < 4; ++iSL) {
859 for (unsigned iwire = 0; iwire < 11; ++iwire) {
860 foundTrack.inputExtraT[iSL][iwire] = mlp_bin_to_signed_int(p_mlpin_extratime.substr((((3 - iSL) *
861 11) + (10 - iwire)) * p_mlpin_extratime.size() / 44, p_mlpin_extratime.size() / 44)) * scale_extratime;
862 foundTrack.rawinputExtraT[iSL][iwire] = mlp_bin_to_signed_int(p_mlpin_extratime.substr((((3 - iSL) *
863 11) + (10 - iwire)) * p_mlpin_extratime.size() / 44, p_mlpin_extratime.size() / 44));
864 }
865 }
866 return foundTrack;
867 }
868 TRGNeuroTrack decodeNNTrack_old(std::string trackIn, std::string selectIn)
869 {
870 constexpr unsigned lenMLP = 13;
871 float scale = 1. / (1 << (lenMLP - 1));
872 TRGNeuroTrack foundTrack;
873 int theta_raw = mlp_bin_to_signed_int(trackIn.substr(1, lenMLP));
874 foundTrack.theta = theta_raw * scale * M_PI_2 + M_PI_2;
875 int z_raw = mlp_bin_to_signed_int(trackIn.substr(lenMLP + 1, lenMLP));
876 foundTrack.z = z_raw * scale * 50.;
877 foundTrack.sector = std::bitset<3>(trackIn.substr(2 * lenMLP + 1, 3)).to_ulong();
878 for (unsigned iSL = 0; iSL < 9; ++iSL) {
879 foundTrack.inputAlpha[iSL] =
880 mlp_bin_to_signed_int(selectIn.substr((2 + (8 - iSL)) * lenMLP + 4, lenMLP)) * scale;
881 foundTrack.inputT[iSL] =
882 mlp_bin_to_signed_int(selectIn.substr((11 + (8 - iSL)) * lenMLP + 4, lenMLP)) * scale;
883 foundTrack.inputID[iSL] =
884 mlp_bin_to_signed_int(selectIn.substr((20 + (8 - iSL)) * lenMLP + 4, lenMLP)) * scale;
885 foundTrack.ts[iSL] = // order: SL8, ..., SL0
886 decodeTSHit(selectIn.substr(29 * lenMLP + 4 + (8 - iSL) * lenTS, lenTS));
887 }
888 return foundTrack;
889 }
890
895 CDCTriggerSegmentHit* addTSHit(tsOut ts, unsigned iSL, unsigned iTracker,
896 StoreArray<CDCTriggerSegmentHit>* tsHits,
897 int foundTime = 0, extraHitTimeOut exTime = {})
898 {
899 unsigned iTS = TSIDInSL(ts[0], iSL, iTracker);
900 // check if hit is already existing in datastore
901 CDCTriggerSegmentHit* hit = nullptr;
902 //for (int ihit = 0; ihit < tsHits->getEntries(); ++ihit) {
903 // CDCTriggerSegmentHit* compare = (*tsHits)[ihit];
904 // if (compare->getISuperLayer() == iSL &&
905 // compare->getIWireCenter() == iTS &&
906 // compare->getPriorityPosition() == ts[3] &&
907 // compare->getLeftRight() == ts[2] &&
908 // compare->priorityTime() == int(ts[1])) {
909 // hit = compare;
910 // break;
911 // }
912 //}
913// !hit is always true.
914// if (!hit) {
915 if (exTime[0] != 0) { //uild tranditional ts first
916 std::vector<float> hittime(exTime.begin() + 1, exTime.end());
917 hit = tsHits->appendNew(iSL, iTS, ts[3], ts[2], ts[1], 0, foundTime, iTracker, hittime, exTime[0]);
918 } else {
919 hit = tsHits->appendNew(iSL, iTS, ts[3], ts[2], ts[1], 0, foundTime, iTracker);
920 }
921 B2DEBUG(15, "make hit at SL " << iSL << " ID " << iTS << " clock " << foundTime << " iTracker " << iTracker);
922// }
923 return hit;
924 }
925
940 void decode2DOutput(short foundTime,
941 T2DOutputBitStream* bits,
942 StoreArray<CDCTriggerTrack>* storeTracks,
943 StoreArray<CDCTriggerFinderClone>* storeClones,
944 StoreArray<CDCTriggerSegmentHit>* tsHits)
945 {
946 const unsigned lenTrack = 121;
947 const unsigned oldTrackWidth = 6;
948 const unsigned foundWidth = 6;
949 std::array<int, 4> posTrack;
950 for (unsigned i = 0; i < posTrack.size(); ++i) {
951 posTrack[i] = oldTrackWidth + foundWidth + lenTrack * i;
952 }
953 for (unsigned iTracker = 0; iTracker < nTrackers; ++iTracker) {
954 const auto slv = bits->signal()[iTracker];
955 std::string strOutput = slv_to_bin_string(slv).
956 substr(clockCounterWidth, T2DOutputWidth - clockCounterWidth);
957 for (unsigned i = 0; i < nMax2DTracksPerClock; ++i) {
958 // The first 6 bits indicate whether a track is found or not
959 if (slv[clockCounterWidth + oldTrackWidth + i] == one_val) {
960 TRG2DFinderTrack trk = decode2DTrack(strOutput.substr(posTrack[i], lenTrack), iTracker);
961 B2DEBUG(15, "2DOut phi0:" << trk.phi0 << ", omega:" << trk.omega
962 << ", at clock " << foundTime << ", tracker " << iTracker);
963 CDCTriggerTrack* track =
964 storeTracks->appendNew(trk.phi0, trk.omega, 0., foundTime, iTracker);
965 CDCTriggerFinderClone* clone =
966 storeClones->appendNew(slv[clockCounterWidth + i] == one_val, iTracker);
967 clone->addRelationTo(track);
968 // TODO: dig out the TS hits in DataStore, and
969 // add relations to them.
970 // Otherwise, create a new TS hit object and add the relation.
971 // However, the fastest time would be lost in this case.
972 // Problem: there might be multiple TS hits with the same ID,
973 // so the foundTime needs to be aligned first in order to compare.
974 for (unsigned iAx = 0; iAx < nAxialTSF; ++iAx) {
975 const auto& ts = trk.ts[iAx];
976 if (ts[3] > 0) {
977 unsigned iTS = TSIDInSL(ts[0], 2 * iAx, iTracker);
978 CDCTriggerSegmentHit* hit =
979 tsHits->appendNew(2 * iAx, // super layer
980 iTS, // TS number in super layer
981 ts[3], // priority position
982 ts[2], // L/R
983 ts[1], // priority time
984 0, // fastest time (unknown)
985 // set to a clock definitely outside the time window to receive the TS from TSF,
986 // so it won't cause any confusion of the TS origin.
987 // what I want to is to set it to (200 + 2DmoduleID[0,1,2,3]),
988 // so one can distinguish in which 2D this track is found.
989 // foundTime); // found time (using the unpacked clock cycle)
990 2000 + iTracker * 100 + foundTime,
991 iTracker); // quadrant
992 track->addRelationTo(hit);
993 }
994 }
995 }
996 }
997 }
998 }
999
1012 void decode2DInput(short foundTime,
1013 std::array<int, 4> timeOffset,
1014 TSFOutputBitStream* bits,
1015 StoreArray<CDCTriggerSegmentHit>* tsHits)
1016 {
1017 // Get the input TS to 2D from the Bitstream
1018 for (unsigned iAx = 0; iAx < nAxialTSF; ++iAx) {
1019 for (unsigned iTracker = 0; iTracker < nTrackers; ++iTracker) {
1020 const auto& tracker = bits->signal()[iAx][iTracker];
1021 std::string strInput = slv_to_bin_string(tracker);
1022 bool noMoreHit = false;
1023 for (unsigned pos = clockCounterWidth; pos < TSFOutputWidth; pos += lenTS) {
1024 std::string tsHitStr = strInput.substr(pos, lenTS);
1025 B2DEBUG(50, tsHitStr);
1026 tsOut ts = decodeTSHit(tsHitStr);
1027 // check if all the hits are on the MSB side
1028 if (ts[2] == 0) {
1029 noMoreHit = true;
1030 continue;
1031 } else if (noMoreHit) {
1032 B2DEBUG(20, "Discontinuous TS hit detected!");
1033 }
1034 unsigned iTS = TSIDInSL(ts[0], 2 * iAx, iTracker);
1035 // Make TS hit object
1036 CDCTriggerSegmentHit hit(2 * iAx, // super layer
1037 iTS, // TS number in super layer
1038 ts[3], // priority position
1039 ts[2], // L/R
1040 ts[1], // priority time
1041 0, // fastest time (unknown)
1042 foundTime + timeOffset[iTracker], // found time
1043 iTracker); // quadrant
1044
1045 // add if the TS hit of identical ID and foundTime is not already in the StoreArray
1046 // (from the 2D input of another quarter or the 2D track output)
1047
1048 /* TODO: Currently, it is very likely that a TS hit will appear
1049 * multiple times in the StoreArray. To avoid adding the input from
1050 * another quarter again, we need to look at the clock counter,
1051 * because the data from different 2D's are not always synchronized
1052 * due to Belle2Link instability. To avoid adding again from the 2D
1053 * output, we need to consider the 2D latency.
1054 */
1055 if (std::none_of(tsHits->begin(), tsHits->end(),
1056 [hit](CDCTriggerSegmentHit storeHit) {
1057 return (storeHit.getSegmentID() == hit.getSegmentID() &&
1058 storeHit.foundTime() == hit.foundTime());
1059 })) {
1060 B2DEBUG(40, "found TS hit ID " << hit.getSegmentID() <<
1061 ", SL" << 2 * iAx << ", local ID " << iTS <<
1062 ", 2D" << iTracker);
1063 tsHits->appendNew(hit);
1064 } else {
1065 B2DEBUG(45, "skipping redundant hit ID " << hit.getSegmentID() << " in 2D" << iTracker);
1066 }
1067 }
1068 }
1069 }
1070 }
1071
1088 CDCTriggerTrack* decodeNNInput(short iclock,
1089 unsigned iTracker,
1090 NNBitStream* bitsIn,
1091 StoreArray<CDCTriggerTrack>* store2DTracks,
1092 StoreArray<CDCTriggerSegmentHit>* tsHits)
1093 {
1094 CDCTriggerTrack* track2D = nullptr;
1095 constexpr unsigned lenTrack = 135; //119;
1096 // omega (7 bit) + phi (7 bit) + 5 * TS (21 bit) + old track found(6bit) + valid stereo bit (1bit) + drift threshold (9bit)
1097 const auto slvIn = bitsIn->signal()[iTracker];
1098 std::string strIn = slv_to_bin_string(slvIn);
1099 strIn = strIn.substr(NN_WIDTH - 570 - 496, 982);
1100 // decode stereo hits
1101 for (unsigned iSt = 0; iSt < nStereoTSF; ++iSt) {
1102 for (unsigned iHit = 0; iHit < 10; ++iHit) {
1103 // order: 10 * SL7, 10 * SL5, 10 * SL3, 10 * SL1
1104 unsigned pos = ((nStereoTSF - iSt - 1) * 10 + iHit) * lenTS;
1105 tsOut ts = decodeTSHit(strIn.substr(pos, lenTS));
1106 if (ts[3] > 0) {
1107 addTSHit(ts, iSt * 2 + 1, iTracker, tsHits, iclock);
1108 }
1109 }
1110 }
1111 std::string strTrack = strIn.substr(nStereoTSF * 10 * lenTS, lenTrack);
1112 if (!std::all_of(strTrack.begin(), strTrack.end(), [](char i) {return i == '0';})) {
1113 std::string infobits = strTrack.substr(5 * lenTS + 14, 16);
1114 strTrack = "00" + strTrack.substr(5 * lenTS, 14) + strTrack.substr(0,
1115 5 * lenTS); // add 2 dummy bits for the charge (not stored in NN)
1116 TRG2DFinderTrack trk2D = decode2DTrack(strTrack, iTracker);
1117 B2DEBUG(15, "NNIn phi0:" << trk2D.phi0 << ", omega:" << trk2D.omega
1118 << ", at clock " << iclock << ", tracker " << iTracker);
1119 B2DEBUG(300, "Content of new infobits: " << infobits);
1120 std::vector<bool> foundoldtrack;
1121 std::vector<bool> driftthreshold;
1122 bool valstereobit;
1123 unsigned i = 0;
1124 for (i = 0; i < 6; i++) {
1125 if (infobits.substr(i, 1) == "1") {
1126 foundoldtrack.push_back(true);
1127 } else if (infobits.substr(i, 1) == "0") {
1128 foundoldtrack.push_back(false);
1129 } else {
1130 B2WARNING("Invalid input in NNBitstream appending 'false'!");
1131 foundoldtrack.push_back(false);
1132 }
1133 }
1134 i = 6;
1135 if (infobits.substr(i, 1) == "1") {
1136 valstereobit = true;
1137 } else if (infobits.substr(i, 1) == "0") {
1138 valstereobit = false;
1139 } else {
1140 B2WARNING("Invalid input in NNBitstream appending 'false'!");
1141 valstereobit = false;
1142 }
1143 for (i = 7; i < 16; i++) {
1144 if (infobits.substr(i, 1) == "1") {
1145 driftthreshold.push_back(true);
1146 } else if (infobits.substr(i, 1) == "0") {
1147 driftthreshold.push_back(false);
1148 } else {
1149 B2WARNING("Invalid input in NNBitstream appending 'false'!");
1150 driftthreshold.push_back(false);
1151 }
1152 }
1153 B2DEBUG(15, "bits for foundoldtrack: " << foundoldtrack[0]
1154 << foundoldtrack[1]
1155 << foundoldtrack[2]
1156 << foundoldtrack[3]
1157 << foundoldtrack[4]
1158 << foundoldtrack[5]);
1159 B2DEBUG(15, "bits for driftthreshold: " << driftthreshold[0]
1160 << driftthreshold[1]
1161 << driftthreshold[2]
1162 << driftthreshold[3]
1163 << driftthreshold[4]
1164 << driftthreshold[5]
1165 << driftthreshold[6]
1166 << driftthreshold[7]
1167 << driftthreshold[8]);
1168 B2DEBUG(15, "bits for valstereobit: " << valstereobit);
1169
1170 // check if 2D track is already in list, otherwise add it
1171 //for (int itrack = 0; itrack < store2DTracks->getEntries(); ++itrack) {
1172 // if ((*store2DTracks)[itrack]->getPhi0() == trk2D->phi0 &&
1173 // (*store2DTracks)[itrack]->getOmega() == trk2D->omega) {
1174 // track2D = (*store2DTracks)[itrack];
1175 // B2DEBUG(15, "found 2D track in store with phi " << trk2D->phi0 << " omega " << trk2D->omega);
1176 // break;
1177 // }
1178 //}
1179 B2DEBUG(15, "make new 2D track with phi " << trk2D.phi0 << " omega " << trk2D.omega << " clock " << iclock);
1180 track2D = store2DTracks->appendNew(trk2D.phi0, trk2D.omega, 0., foundoldtrack, driftthreshold, valstereobit, iclock, iTracker);
1181 // add axial hits and create relations
1182 for (unsigned iAx = 0; iAx < nAxialTSF; ++iAx) {
1183 const auto& ts = trk2D.ts[iAx];
1184 if (ts[3] > 0) {
1185 CDCTriggerSegmentHit* hit =
1186 addTSHit(ts, 2 * iAx, iTracker, tsHits, iclock);
1187 track2D->addRelationTo(hit);
1188 }
1189 }
1190 // TODO: decode event time
1191 }
1192 return track2D;
1193 }
1194
1215 void decodeNNOutput_old(short foundTime,
1216 unsigned iTracker,
1217 NNBitStream* bitsOut,
1218 NNBitStream* bitsSelectTS,
1219 StoreArray<CDCTriggerTrack>* storeNNTracks,
1220 StoreArray<CDCTriggerSegmentHit>* tsHits,
1221 StoreArray<CDCTriggerMLPInput>* storeNNInputs,
1222 CDCTriggerTrack* track2D)
1223 {
1224 const auto slvOut = bitsOut->signal()[iTracker];
1225 std::string strTrack = slv_to_bin_string(slvOut);
1226 strTrack = strTrack.substr(496, 570);
1227 const auto slvSelect = bitsSelectTS->signal()[iTracker];
1228 std::string strSelect = slv_to_bin_string(slvSelect);
1229 strSelect = strSelect.substr(496, 570);
1230 TRGNeuroTrack trkNN = decodeNNTrack_old(strTrack, strSelect);
1231 B2DEBUG(15, "make new NN track with , z:" << trkNN.z << ", theta:" << trkNN.theta <<
1232 ", sector:" << trkNN.sector << ", clock " << foundTime);
1233 double phi0 = 0;
1234 double omega = 0;
1235 if (track2D) {
1236 phi0 = track2D->getPhi0();
1237 omega = track2D->getOmega();
1238 }
1239 std::vector<unsigned> tsvector(9, 0);
1240 for (unsigned iSL = 0; iSL < 9; ++iSL) {
1241 tsvector[iSL] = trkNN.ts[iSL][2]; // save lr info in tsvector array
1242 }
1243 CDCTriggerTrack* trackNN = storeNNTracks->appendNew(phi0, omega, 0.,
1244 trkNN.z, cos(trkNN.theta) / sin(trkNN.theta), 0., track2D->getFoundOldTrack(), track2D->getDriftThreshold(),
1245 track2D->getValidStereoBit(), trkNN.sector, tsvector, foundTime, iTracker);
1246 std::vector<float> inputVector(27, 0.);
1247 for (unsigned iSL = 0; iSL < 9; ++iSL) {
1248 inputVector[3 * iSL] = trkNN.inputID[iSL];
1249 inputVector[3 * iSL + 1] = trkNN.inputT[iSL];
1250 inputVector[3 * iSL + 2] = trkNN.inputAlpha[iSL];
1251 }
1252 CDCTriggerMLPInput* storeInput =
1253 storeNNInputs->appendNew(inputVector, trkNN.sector);
1254 trackNN->addRelationTo(storeInput);
1255 track2D->addRelationTo(trackNN);
1256
1257 for (unsigned iSL = 0; iSL < 9; ++iSL) {
1258 if (trkNN.ts[iSL][3] > 0) {
1259 CDCTriggerSegmentHit* hit = addTSHit(trkNN.ts[iSL], iSL, iTracker, tsHits, foundTime);
1260 trackNN->addRelationTo(hit);
1261 }
1262 }
1263 }
1264
1265
1266
1267
1268
1269
1270
1271
1288 void decodeNNIO(
1289 StoreArray<CDCTriggerUnpacker::NNBitStream>* bitsNN,
1290 StoreArray<CDCTriggerTrack>* store2DTracks,
1291 StoreArray<CDCTriggerTrack>* storeNNTracks,
1292 StoreArray<CDCTriggerSegmentHit>* tsHits,
1293 StoreArray<CDCTriggerSegmentHit>* tsHitsAll,
1294 StoreArray<CDCTriggerMLPInput>* storeNNInputs,
1295 StoreObjPtr<BinnedEventT0> storeETFTime,
1296 const DBObjPtr<CDCTriggerNeuroConfig> neurodb,
1297 bool sim13dt)
1298 {
1299 for (unsigned iTracker = 0; iTracker < nTrackers; ++iTracker) {
1300 B2DEBUG(21, "----------------------------------------------------------------------------------------------------");
1301 B2DEBUG(21, padright(" Unpacking Tracker: " + std::to_string(iTracker), 100));
1302 // loop over boards belonging to geometrical sectors
1303
1304 for (short iclock = 0; iclock < bitsNN->getEntries(); ++iclock) {
1305 // check for NNEnable bit:
1306 B2LDataField p_nnenable(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("NNEnable"));
1307 if (p_nnenable.name == "None") {
1308 B2DEBUG(5, "Neurotrigger: NNENable position unknown, skipping ... ");
1309 continue;
1310 } else if (p_nnenable.data == "1") {
1311 B2DEBUG(10, padright("Tracker: " + std::to_string(iTracker) + ", Clock: " + std::to_string(iclock) + " : NNEnable set!", 100));
1312 } else {
1313 B2DEBUG(21, padright(" UnpackerClock: " + std::to_string(iclock), 100));
1314 }
1315
1316
1317 CDCTriggerNeuroConfig::B2FormatLine nnall;
1318 nnall.start = 0;
1319 nnall.end = 2047;
1320 nnall.offset = 0;
1321 nnall.name = "nnall";
1322 B2LDataField p_nnall(bitsNN, iclock, iTracker, nnall);
1323 B2DEBUG(22, padright(" all bits: ", 100));
1324 B2DEBUG(22, padright(" " + p_nnall.data, 100));
1325 // define variables to fill from the bitstream, B2LDataField holds just the string, not the unpacked data yet
1326 B2LDataField p_driftthreshold(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("DriftThreshold"));
1327 if ((p_driftthreshold.name != "None") && (p_driftthreshold.data.size() == 0)) {
1328 B2DEBUG(10, "Could not load Datafield: " << p_driftthreshold.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1329 iclock);
1330 continue;
1331 }
1332
1333 B2LDataField p_valstereobit(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("ValStereoBit"));
1334 if ((p_valstereobit.name != "None") && (p_valstereobit.data.size() == 0)) {
1335 B2DEBUG(10, "Could not load Datafield: " << p_valstereobit.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1336 iclock);
1337 continue;
1338 }
1339
1340 B2LDataField p_foundoldtrack(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("FoundOldTrack"));
1341 if ((p_foundoldtrack.name != "None") && (p_foundoldtrack.data.size() == 0)) {
1342 B2DEBUG(10, "Could not load Datafield: " << p_foundoldtrack.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1343 iclock);
1344 continue;
1345 }
1346
1347 B2LDataField p_phi(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("Phi"));
1348 if ((p_phi.name != "None") && (p_phi.data.size() == 0)) {
1349 B2DEBUG(10, "Could not load Datafield: " << p_phi.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1350 continue;
1351 }
1352
1353 B2LDataField p_omega(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("Omega"));
1354 if ((p_omega.name != "None") && (p_omega.data.size() == 0)) {
1355 B2DEBUG(10, "Could not load Datafield: " << p_omega.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1356 continue;
1357 }
1358
1359 B2LDataField p_ts8(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS8"));
1360 if ((p_ts8.name != "None") && (p_ts8.data.size() == 0)) {
1361 B2DEBUG(10, "Could not load Datafield: " << p_ts8.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1362 continue;
1363 }
1364
1365 B2LDataField p_ts6(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS6"));
1366 if ((p_ts6.name != "None") && (p_ts6.data.size() == 0)) {
1367 B2DEBUG(10, "Could not load Datafield: " << p_ts6.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1368 continue;
1369 }
1370
1371 B2LDataField p_ts4(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS4"));
1372 if ((p_ts4.name != "None") && (p_ts4.data.size() == 0)) {
1373 B2DEBUG(10, "Could not load Datafield: " << p_ts4.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1374 continue;
1375 }
1376
1377 B2LDataField p_ts2(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS2"));
1378 if ((p_ts2.name != "None") && (p_ts2.data.size() == 0)) {
1379 B2DEBUG(10, "Could not load Datafield: " << p_ts2.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1380 continue;
1381 }
1382
1383 B2LDataField p_ts0(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS0"));
1384 if ((p_ts0.name != "None") && (p_ts0.data.size() == 0)) {
1385 B2DEBUG(10, "Could not load Datafield: " << p_ts0.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1386 continue;
1387 }
1388
1389 B2LDataField p_tsf1(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSF1"));
1390 if ((p_tsf1.name != "None") && (p_tsf1.data.size() == 0)) {
1391 B2DEBUG(10, "Could not load Datafield: " << p_tsf1.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1392 continue;
1393 }
1394
1395 B2LDataField p_tsf3(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSF3"));
1396 if ((p_tsf3.name != "None") && (p_tsf3.data.size() == 0)) {
1397 B2DEBUG(10, "Could not load Datafield: " << p_tsf3.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1398 continue;
1399 }
1400
1401 B2LDataField p_tsf5(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSF5"));
1402 if ((p_tsf5.name != "None") && (p_tsf5.data.size() == 0)) {
1403 B2DEBUG(10, "Could not load Datafield: " << p_tsf5.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1404 continue;
1405 }
1406
1407 B2LDataField p_tsf7(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSF7"));
1408 if ((p_tsf7.name != "None") && (p_tsf7.data.size() == 0)) {
1409 B2DEBUG(10, "Could not load Datafield: " << p_tsf7.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1410 continue;
1411 }
1412
1413 B2LDataField p_tsfsel(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSFsel"));
1414 if ((p_tsfsel.name != "None") && (p_tsfsel.data.size() == 0)) {
1415 B2DEBUG(10, "Could not load Datafield: " << p_tsfsel.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1416 continue;
1417 }
1418
1419 B2LDataField p_mlpin_alpha(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPIn_alpha"));
1420 if ((p_mlpin_alpha.name != "None") && (p_mlpin_alpha.data.size() == 0)) {
1421 B2DEBUG(10, "Could not load Datafield: " << p_mlpin_alpha.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1422 iclock);
1423 continue;
1424 }
1425
1426 B2LDataField p_mlpin_drifttime(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPIn_driftt"));
1427 if ((p_mlpin_drifttime.name != "None") && (p_mlpin_drifttime.data.size() == 0)) {
1428 B2DEBUG(10, "Could not load Datafield: " << p_mlpin_drifttime.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1429 iclock);
1430 continue;
1431 }
1432
1433 B2LDataField p_mlpin_id(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPIn_id"));
1434 if ((p_mlpin_id.name != "None") && (p_mlpin_id.data.size() == 0)) {
1435 B2DEBUG(10, "Could not load Datafield: " << p_mlpin_id.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1436 iclock);
1437 continue;
1438 }
1439
1440 B2LDataField p_netsel(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("Netsel"));
1441 if ((p_netsel.name != "None") && (p_netsel.data.size() == 0)) {
1442 B2DEBUG(10, "Could not load Datafield: " << p_netsel.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1443 continue;
1444 }
1445
1446 B2LDataField p_mlpout_z(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPOut_z"));
1447 if ((p_mlpout_z.name != "None") && (p_mlpout_z.data.size() == 0)) {
1448 B2DEBUG(10, "Could not load Datafield: " << p_mlpout_z.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1449 iclock);
1450 continue;
1451 }
1452
1453 B2LDataField p_mlpout_theta(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPOut_theta"));
1454 if ((p_mlpout_theta.name != "None") && (p_mlpout_theta.data.size() == 0)) {
1455 B2DEBUG(10, "Could not load Datafield: " << p_mlpout_theta.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1456 iclock);
1457 continue;
1458 }
1459
1460 B2LDataField p_2dcc(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("2dcc"));
1461 if ((p_2dcc.name != "None") && (p_2dcc.data.size() == 0)) {
1462 B2DEBUG(10, "Could not load Datafield: " << p_2dcc.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1463 continue;
1464 }
1465
1466 B2LDataField p_extendedpts(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("extendedPriorityTimes"));
1467 if ((p_extendedpts.name != "None") && (p_extendedpts.data.size() == 0)) {
1468 B2DEBUG(10, "Could not load Datafield: " << p_extendedpts.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1469 iclock);
1470 continue;
1471 }
1472 B2LDataField p_etftime(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etftime"));
1473 if ((p_etftime.name != "None") && (p_etftime.data.size() == 0)) {
1474 B2DEBUG(10, "Could not load Datafield: " << p_etftime.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1475 iclock);
1476 continue;
1477 }
1478 B2LDataField p_etfcc(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etfcc"));
1479 if ((p_etfcc.name != "None") && (p_etfcc.data.size() == 0)) {
1480 B2DEBUG(10, "Could not load Datafield: " << p_etfcc.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1481 iclock);
1482 continue;
1483 }
1484 B2LDataField p_etfqual(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etfquality"));
1485 if ((p_etfqual.name != "None") && (p_etfqual.data.size() == 0)) {
1486 B2DEBUG(10, "Could not load Datafield: " << p_etfqual.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1487 iclock);
1488 continue;
1489 }
1490 B2LDataField p_etfval(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etfvalid"));
1491 if ((p_etfval.name != "None") && (p_etfval.data.size() == 0)) {
1492 B2DEBUG(10, "Could not load Datafield: " << p_etfval.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1493 iclock);
1494 continue;
1495 }
1496 B2LDataField p_nntgdl(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("nntgdl"));
1497 if ((p_nntgdl.name != "None") && (p_nntgdl.data.size() == 0)) {
1498 B2DEBUG(10, "Could not load Datafield: " << p_nntgdl.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1499 iclock);
1500 continue;
1501 }
1502 B2LDataField p_sttgdl(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("sttgdl"));
1503 if ((p_sttgdl.name != "None") && (p_sttgdl.data.size() == 0)) {
1504 B2DEBUG(10, "Could not load Datafield: " << p_sttgdl.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1505 iclock);
1506 continue;
1507 }
1508
1509 // B2LDataField (bitsNN, iclock, iTracker, neurodb->getB2FormatLine(""));
1510
1511 CDCTriggerTrack* track2D = nullptr;
1512 // decode stereo hits
1513 if (true) { // (p_nnenable.data == "1") {
1514 unsigned sln = 0;
1515 B2DEBUG(21, padright(" Stereos: ", 100));
1516 for (auto stereolayer : {p_tsf1, p_tsf3, p_tsf5, p_tsf7}) {
1517 if (stereolayer.name == "None") {
1518 B2ERROR("Error in CDCTriggerNeuroConfig Payload, position of stereo tsf could not be found!");
1519 continue;
1520 }
1521 std::string tsstr = " | ";
1522 for (unsigned iHit = 0; iHit < 10; ++iHit) {
1523 tsOut ts = (sim13dt) ? decodeTSHit_sim(stereolayer.data.substr(iHit * lenTS, lenTS),
1524 p_2dcc.data) : decodeTSHit(stereolayer.data.substr(iHit * lenTS, lenTS));
1525 if (ts[3] > 0) { // if it is 0, it means 'no hit'
1526 unsigned iTS = TSIDInSL(ts[0], sln * 2 + 1, iTracker);
1527 tsstr += std::to_string(iTS) + ", " + std::to_string(ts[1]) + ", " + std::to_string(ts[2]) + ", " + std::to_string(ts[3]) + " | ";
1528 addTSHit(ts, sln * 2 + 1, iTracker, tsHitsAll, iclock);
1529 }
1530 }
1531 B2DEBUG(21, padright(" SL" + std::to_string(sln * 2 + 1) + tsstr, 100));
1532 ++sln;
1533 }
1534 }
1535 B2DEBUG(21, padright(" 2DCC: " + std::to_string(std::stoi(p_2dcc.data, 0, 2)) + ", (" + p_2dcc.data + ")", 100));
1536 B2DEBUG(21, padright(" ETFCC: " + std::to_string(std::stoi(p_etfcc.data, 0, 2)) + ", (" + p_etfcc.data + ")", 100));
1537 B2DEBUG(21, padright(" ETFVAL: " + std::to_string(std::stoi(p_etfval.data, 0, 2)) + ", (" + p_etfval.data + ")", 100));
1538 B2DEBUG(21, padright(" ETFT0: " + std::to_string(std::stoi(p_etftime.data, 0, 2)) + ", (" + p_etftime.data + ")", 100));
1539 B2DEBUG(21, padright(" ETFQuality: " + std::to_string(std::stoi(p_etfqual.data, 0, 2)) + ", (" + p_etfqual.data + ")", 100));
1540 if (p_nnenable.data == "1") {
1541 bool hasETFTime = false;
1542 if (p_etfval.data == "1") {
1543 storeETFTime->addBinnedEventT0(std::stoi(p_etftime.data, 0, 2), Const::CDC);
1544 hasETFTime = true;
1545 }
1546 std::vector<bool> foundoldtrack{false};
1547 std::vector<bool> driftthreshold{false};
1548 bool valstereobit;
1549 if (p_foundoldtrack.name != "None") {
1550 foundoldtrack = decodefoundoldtrack(p_foundoldtrack.data);
1551 }
1552 if (p_driftthreshold.name != "None") {
1553 driftthreshold = decodedriftthreshold(p_driftthreshold.data);
1554 }
1555 if (p_valstereobit.name != "None") {
1556 valstereobit = decodevalstereobit(p_valstereobit.data);
1557 }
1558
1559 if (std::all_of(p_phi.data.begin(), p_phi.data.end(), [](char i) {return i == 0;})) {
1560 B2ERROR("Empty Phi Value found for 2DTrack, should not happen!");
1561 continue;
1562 }
1563 TRG2DFinderTrack trk2D = decode2DTrack(
1564 "00", //charge
1565 p_omega.data,
1566 p_phi.data,
1567 p_ts0.data,
1568 p_ts2.data,
1569 p_ts4.data,
1570 p_ts6.data,
1571 p_ts8.data,
1572 iTracker,
1573 p_2dcc.data,
1574 sim13dt);
1575 track2D = store2DTracks->appendNew(trk2D.phi0, trk2D.omega, 0., foundoldtrack, driftthreshold, valstereobit, iclock, iTracker);
1576 track2D->setRawOmega(trk2D.hwOmega);
1577 track2D->setRawPhi0(trk2D.hwPhi0);
1578 B2DEBUG(12, padright(" 2DTrack: (phi=" + std::to_string(trk2D.phi0) + ", omega=" + std::to_string(
1579 trk2D.omega) + ", update=" + std::to_string(foundoldtrack[1]) + ")", 100));
1580
1581 // add axial hits and create relations
1582 std::string tsstr;
1583 for (unsigned iAx = 0; iAx < nAxialTSF; ++iAx) {
1584 const auto& ts = trk2D.ts[iAx];
1585 if (ts[3] > 0) {
1586 CDCTriggerSegmentHit* hit =
1587 addTSHit(ts, 2 * iAx, iTracker, tsHitsAll, iclock);
1588 unsigned iTS = TSIDInSL(ts[0], iAx * 2, iTracker);
1589 tsstr += "(SL" + std::to_string(iAx * 2) + ", " + std::to_string(iTS) + ", " + std::to_string(ts[1]) + ", " + std::to_string(
1590 ts[2]) + ", " + std::to_string(ts[3]) + "),";
1591 track2D->addRelationTo(hit);
1592 }
1593 }
1594 B2DEBUG(16, padright(" 2DTrack TS: " + tsstr, 100));
1595
1596
1597 if (track2D) {
1598 TRGNeuroTrack trkNN;
1599 trkNN = decodeNNTrack(p_mlpout_z.data,
1600 p_mlpout_theta.data,
1601 p_tsfsel.data,
1602 p_mlpin_alpha.data,
1603 p_mlpin_drifttime.data,
1604 p_mlpin_id.data,
1605 p_netsel.data,
1606 neurodb,
1607 p_2dcc.data,
1608 sim13dt,
1609 p_extendedpts);
1610
1611
1612 B2DEBUG(11, padright(" NNTrack: (z=" + std::to_string(trkNN.z) + ", theta=" + std::to_string(trkNN.theta) + ")", 100));
1613
1614 double phi0 = track2D->getPhi0();
1615 double omega = track2D->getOmega();
1616
1617 std::vector<unsigned> tsvector(9, 0);
1618 std::vector<unsigned> tstimevector(9, 0);
1619 tsstr = "";
1620 // turns false, as soon as there is a ts, which is not contained in the 2dfindertrack
1621 bool isin2d = true;
1622 for (unsigned iSL = 0; iSL < 9; ++iSL) {
1623 tsvector[iSL] = trkNN.ts[iSL][3];
1624 tstimevector[iSL] = trkNN.ts[iSL][1];
1625 if (trkNN.ts[iSL][3] > 0) {
1626 unsigned iTS = TSIDInSL(trkNN.ts[iSL][0], iSL, iTracker);
1627 tsstr += "(SL" + std::to_string(iSL) + ", " + std::to_string(iTS) + ", " + std::to_string(trkNN.ts[iSL][1]) + ", " + std::to_string(
1628 trkNN.ts[iSL][2]) + ", " + std::to_string(trkNN.ts[iSL][3]) + "),\n";
1629 // check, whether axials are a subset of 2dfinderTS:
1630 if (iSL % 2 == 0) {
1631 if (!(trk2D.ts[iSL / 2][0] == trkNN.ts[iSL][0] &&
1632 //trk2D.ts[iSL / 2][1] == trkNN.ts[iSL][1] &&
1633 trk2D.ts[iSL / 2][2] == trkNN.ts[iSL][2] &&
1634 trk2D.ts[iSL / 2][3] == trkNN.ts[iSL][3])) {
1635 isin2d = false;
1636 }
1637 }
1638
1639 } else {
1640 tsstr += "( - ),\n";
1641 }
1642 }
1643
1644 B2DEBUG(15, padright(" NNTrack TS: " + tsstr, 100));
1645
1646 CDCTriggerTrack* trackNN = storeNNTracks->appendNew(phi0, omega, 0.,
1647 trkNN.z, cos(trkNN.theta) / sin(trkNN.theta), 0., track2D->getFoundOldTrack(), track2D->getDriftThreshold(),
1648 track2D->getValidStereoBit(), trkNN.sector, tsvector, iclock, iTracker);
1649 trackNN->setHasETFTime(hasETFTime);
1650 track2D->setHasETFTime(hasETFTime);
1651 trackNN->setRawOmega(track2D->getRawOmega());
1652 trackNN->setRawPhi0(track2D->getRawPhi0());
1653 trackNN->setRawTheta(trkNN.hwTheta);
1654 trackNN->setRawZ(trkNN.hwZ);
1655 if (hasETFTime) {
1656 trackNN->setETF_unpacked(std::stoi(p_etftime.data, 0, 2));
1657 track2D->setETF_unpacked(std::stoi(p_etftime.data, 0, 2));
1658 }
1659 trackNN->setETF_recalced(recalcETF(p_mlpin_drifttime.data, tstimevector, trackNN));
1660 track2D->setETF_recalced(recalcETF(p_mlpin_drifttime.data, tstimevector, trackNN));
1661
1662 if (isin2d == false) {
1663 trackNN->setQualityVector(1);
1664 }
1665 std::vector<float> inputVector(27, 0.);
1666 std::vector<int> rawinputVector(27, 0.);
1667 for (unsigned iSL = 0; iSL < 9; ++iSL) {
1668 inputVector[3 * iSL] = trkNN.inputID[iSL];
1669 inputVector[3 * iSL + 1] = trkNN.inputT[iSL];
1670 inputVector[3 * iSL + 2] = trkNN.inputAlpha[iSL];
1671 rawinputVector[3 * iSL] = trkNN.rawinputID[iSL];
1672 rawinputVector[3 * iSL + 1] = trkNN.rawinputT[iSL];
1673 rawinputVector[3 * iSL + 2] = trkNN.rawinputAlpha[iSL];
1674 }
1675 trackNN->setRawInput(rawinputVector);
1676
1677 CDCTriggerMLPInput* storeInput =
1678 storeNNInputs->appendNew(inputVector, trkNN.sector);
1679 trackNN->addRelationTo(storeInput);
1680 track2D->addRelationTo(trackNN);
1681
1682 for (unsigned iSL = 0; iSL < 9; ++iSL) {
1683 if (trkNN.ts[iSL][3] > 0) {
1684 CDCTriggerSegmentHit* hit = nullptr;
1685 // if (sim13dt) {
1686 // // get extended priority time for stereos from the allstereots storearray
1687 // for (int ihit = 0; ihit<tsHitsAll->getEntries(); ++ihit) {
1688 // CDCTriggerSegmentHit* compare = (*tsHitsAll)[ihit];
1689 // if (compare->getISuperLayer() == iSL &&
1690 // compare->getIWireCenter() == TSIDInSL(trkNN.ts[iSL][0], iSL, iTracker) &&
1691 // compare->getPriorityPosition() == trkNN.ts[iSL][3] &&
1692 // compare->getLeftRight() == trkNN.ts[iSL][2] ) {
1693 // hit = compare;
1694 // }
1695 // }
1696 // if (!(!hit)) {
1697 // tsHits->appendNew(hit->getISuperLayer(), hit->getIWireCenter(), hit->getPriorityPosition(), hit->getLeftRight(), hit->priorityTime(), 0, hit->foundTime(), iTracker);
1698 // }
1699 // // get the extended pt for axials from the already existing 2d TS
1700 // for (int ihit = 0; ihit<tsHits->getEntries(); ++ihit) {
1701 // CDCTriggerSegmentHit* compare = (*tsHits)[ihit];
1702 // if (compare->getISuperLayer() == iSL &&
1703 // compare->getIWireCenter() == TSIDInSL(trkNN.ts[iSL][0], iSL, iTracker) &&
1704 // compare->getPriorityPosition() == trkNN.ts[iSL][3] &&
1705 // compare->getLeftRight() == trkNN.ts[iSL][2] ) {
1706 // hit = compare;
1707 // }
1708 // }
1709
1710 // }
1711
1712 // cppcheck-suppress knownConditionTrueFalse
1713 if (!hit) {
1714 hit = addTSHit(trkNN.ts[iSL], iSL, iTracker, tsHits, iclock);
1715 // B2DEBUG(1, "Hit with short drift time added, should not happen!");
1716 // }
1717 }
1718 trackNN->addRelationTo(hit);
1719 if (iSL % 2 == 0) {
1720 track2D->addRelationTo(hit);
1721 }
1722 }
1723 }
1724 if (p_nntgdl.name != "None") {
1725 bool dbool = decodebool(p_nntgdl.data);
1726 trackNN->setNNTToGDL(dbool);
1727 B2DEBUG(20, "NNT to GDL Bit decision for this track is: " << dbool);
1728 }
1729 if (p_sttgdl.name != "None") {
1730 bool dbool = decodebool(p_sttgdl.data);
1731 trackNN->setSTTToGDL(dbool);
1732 B2DEBUG(20, "STT to GDL Bit decision for this track is: " << dbool);
1733 }
1734
1735 }
1736
1737
1738 //
1739 // B2DEBUG(15, "bits for foundoldtrack: ");
1740 // for (auto x : foundoldtrack) {
1741 // B2DEBUG(15, x);
1742 // }
1743 // B2DEBUG(15, "bits for driftthreshold: ");
1744 // for (auto x : driftthreshold) {
1745 // B2DEBUG(15, x);
1746 // }
1747 // B2DEBUG(15, "bits for valstereobit: " << valstereobit);
1748 // B2DEBUG(15, "make new 2D track with phi " << trk2D.phi0 << " omega " << trk2D.omega << " clock " << iclock);
1749
1750 }
1751 }
1752 }
1753 }
1754
1755
1778 void decodeDNNIO(
1779 StoreArray<CDCTriggerUnpacker::DNNBitStream>* bitsNN,
1780 StoreArray<CDCTriggerTrack>* store2DTracks,
1781 StoreArray<CDCTriggerTrack>* storeNNTracks,
1782 StoreArray<CDCTriggerSegmentHit>* tsHits,
1783 StoreArray<CDCTriggerSegmentHit>* tsHitsAll,
1784 StoreArray<CDCTriggerMLPInput>* storeNNInputs,
1785 StoreObjPtr<BinnedEventT0> storeETFTime,
1786 const DBObjPtr<CDCTriggerNeuroConfig> neurodb,
1787 bool sim13dt)
1788 {
1789 for (unsigned iTracker = 0; iTracker < nTrackers; ++iTracker) {
1790 B2DEBUG(21, "----------------------------------------------------------------------------------------------------");
1791 B2DEBUG(21, padright(" Unpacking Tracker: " + std::to_string(iTracker), 100));
1792 // loop over boards belonging to geometrical sectors
1793
1794 for (short iclock = 0; iclock < bitsNN->getEntries(); ++iclock) {
1795 // check for NNEnable bit:
1796
1797
1798 B2LDataField_DNN p_nnenable(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("NNEnable"));
1799 if (p_nnenable.name == "None") {
1800 B2DEBUG(5, "Neurotrigger: NNENable position unknown, skipping ... ");
1801 continue;
1802 } else if (p_nnenable.data == "1") {
1803 B2DEBUG(10, padright("Tracker: " + std::to_string(iTracker) + ", Clock: " + std::to_string(iclock) + " : NNEnable set!", 100));
1804 } else {
1805 B2DEBUG(21, padright(" UnpackerClock: " + std::to_string(iclock), 100));
1806 }
1807
1808
1809 CDCTriggerNeuroConfig::B2FormatLine nnall;
1810 nnall.start = 0;
1811 nnall.end = 2047;
1812 nnall.offset = 0;
1813 nnall.name = "nnall";
1814 B2LDataField_DNN p_nnall(bitsNN, iclock, iTracker, nnall);
1815 B2DEBUG(22, padright(" all bits: ", 100));
1816 B2DEBUG(22, padright(" " + p_nnall.data, 100));
1817 // define variables to fill from the bitstream, B2LDataField_DNN holds just the string, not the unpacked data yet
1818 B2LDataField_DNN p_driftthreshold(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("DriftThreshold"));
1819 if ((p_driftthreshold.name != "None") && (p_driftthreshold.data.size() == 0)) {
1820 B2DEBUG(10, "Could not load Datafield: " << p_driftthreshold.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1821 iclock);
1822 continue;
1823 }
1824
1825 B2LDataField_DNN p_valstereobit(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("ValStereoBit"));
1826 if ((p_valstereobit.name != "None") && (p_valstereobit.data.size() == 0)) {
1827 B2DEBUG(10, "Could not load Datafield: " << p_valstereobit.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1828 iclock);
1829 continue;
1830 }
1831 B2LDataField_DNN p_foundoldtrack(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("FoundOldTrack"));
1832 if ((p_foundoldtrack.name != "None") && (p_foundoldtrack.data.size() == 0)) {
1833 B2DEBUG(10, "Could not load Datafield: " << p_foundoldtrack.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1834 iclock);
1835 continue;
1836 }
1837
1838 B2LDataField_DNN p_phi(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("Phi"));
1839 if ((p_phi.name != "None") && (p_phi.data.size() == 0)) {
1840 B2DEBUG(10, "Could not load Datafield: " << p_phi.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1841 continue;
1842 }
1843
1844 B2LDataField_DNN p_omega(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("Omega"));
1845 if ((p_omega.name != "None") && (p_omega.data.size() == 0)) {
1846 B2DEBUG(10, "Could not load Datafield: " << p_omega.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1847 continue;
1848 }
1849
1850 B2LDataField_DNN p_ts8(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS8"));
1851 if ((p_ts8.name != "None") && (p_ts8.data.size() == 0)) {
1852 B2DEBUG(10, "Could not load Datafield: " << p_ts8.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1853 continue;
1854 }
1855
1856 B2LDataField_DNN p_ts6(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS6"));
1857 if ((p_ts6.name != "None") && (p_ts6.data.size() == 0)) {
1858 B2DEBUG(10, "Could not load Datafield: " << p_ts6.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1859 continue;
1860 }
1861
1862 B2LDataField_DNN p_ts4(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS4"));
1863 if ((p_ts4.name != "None") && (p_ts4.data.size() == 0)) {
1864 B2DEBUG(10, "Could not load Datafield: " << p_ts4.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1865 continue;
1866 }
1867
1868 B2LDataField_DNN p_ts2(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS2"));
1869 if ((p_ts2.name != "None") && (p_ts2.data.size() == 0)) {
1870 B2DEBUG(10, "Could not load Datafield: " << p_ts2.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1871 continue;
1872 }
1873
1874 B2LDataField_DNN p_ts0(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TS0"));
1875 if ((p_ts0.name != "None") && (p_ts0.data.size() == 0)) {
1876 B2DEBUG(10, "Could not load Datafield: " << p_ts0.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1877 continue;
1878 }
1879
1880 B2LDataField_DNN p_tsf1(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSF1"));
1881 if ((p_tsf1.name != "None") && (p_tsf1.data.size() == 0)) {
1882 B2DEBUG(10, "Could not load Datafield: " << p_tsf1.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1883 continue;
1884 }
1885
1886 B2LDataField_DNN p_tsf3(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSF3"));
1887 if ((p_tsf3.name != "None") && (p_tsf3.data.size() == 0)) {
1888 B2DEBUG(10, "Could not load Datafield: " << p_tsf3.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1889 continue;
1890 }
1891
1892 B2LDataField_DNN p_tsf5(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSF5"));
1893 if ((p_tsf5.name != "None") && (p_tsf5.data.size() == 0)) {
1894 B2DEBUG(10, "Could not load Datafield: " << p_tsf5.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1895 continue;
1896 }
1897
1898 B2LDataField_DNN p_tsf7(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSF7"));
1899 if ((p_tsf7.name != "None") && (p_tsf7.data.size() == 0)) {
1900 B2DEBUG(10, "Could not load Datafield: " << p_tsf7.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1901 continue;
1902 }
1903
1904 B2LDataField_DNN p_tsfsel(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("TSFsel"));
1905 if ((p_tsfsel.name != "None") && (p_tsfsel.data.size() == 0)) {
1906 B2DEBUG(10, "Could not load Datafield: " << p_tsfsel.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1907 continue;
1908 }
1909
1910 B2LDataField_DNN p_mlpin_alpha(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPIn_alpha"));
1911 if ((p_mlpin_alpha.name != "None") && (p_mlpin_alpha.data.size() == 0)) {
1912 B2DEBUG(10, "Could not load Datafield: " << p_mlpin_alpha.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1913 iclock);
1914 continue;
1915 }
1916
1917 B2LDataField_DNN p_mlpin_drifttime(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPIn_driftt"));
1918 if ((p_mlpin_drifttime.name != "None") && (p_mlpin_drifttime.data.size() == 0)) {
1919 B2DEBUG(10, "Could not load Datafield: " << p_mlpin_drifttime.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1920 iclock);
1921 continue;
1922 }
1923
1924 B2LDataField_DNN p_mlpin_id(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPIn_id"));
1925 if ((p_mlpin_id.name != "None") && (p_mlpin_id.data.size() == 0)) {
1926 B2DEBUG(10, "Could not load Datafield: " << p_mlpin_id.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1927 iclock);
1928 continue;
1929 }
1930
1931 B2LDataField_DNN p_mlpin_extratime(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPIn_extrat"));
1932 if ((p_mlpin_id.name != "None") && (p_mlpin_id.data.size() == 0)) {
1933 B2DEBUG(10, "Could not load Datafield: " << p_mlpin_id.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1934 iclock);
1935 continue;
1936 }
1937
1938 B2LDataField_DNN p_netsel(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("Netsel"));
1939 if ((p_netsel.name != "None") && (p_netsel.data.size() == 0)) {
1940 B2DEBUG(10, "Could not load Datafield: " << p_netsel.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1941 continue;
1942 }
1943
1944 B2LDataField_DNN p_mlpout_z(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPOut_z"));
1945 if ((p_mlpout_z.name != "None") && (p_mlpout_z.data.size() == 0)) {
1946 B2DEBUG(10, "Could not load Datafield: " << p_mlpout_z.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1947 iclock);
1948 continue;
1949 }
1950
1951 B2LDataField_DNN p_mlpout_theta(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPOut_theta"));
1952 if ((p_mlpout_theta.name != "None") && (p_mlpout_theta.data.size() == 0)) {
1953 B2DEBUG(10, "Could not load Datafield: " << p_mlpout_theta.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1954 iclock);
1955 continue;
1956 }
1957
1958 B2LDataField_DNN p_mlpout_prob(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("MLPOut_p"));
1959 if ((p_mlpout_prob.name != "None") && (p_mlpout_prob.data.size() == 0)) {
1960 B2DEBUG(10, "Could not load Datafield: " << p_mlpout_prob.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1961 iclock);
1962 continue;
1963 }
1964 B2LDataField_DNN p_2dcc(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("2dcc"));
1965 if ((p_2dcc.name != "None") && (p_2dcc.data.size() == 0)) {
1966 B2DEBUG(10, "Could not load Datafield: " << p_2dcc.name << " from bitstream. Maybe offset was out of bounds? clock: " << iclock);
1967 continue;
1968 }
1969
1970 B2LDataField_DNN p_extendedpts(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("extendedPriorityTimes"));
1971 if ((p_extendedpts.name != "None") && (p_extendedpts.data.size() == 0)) {
1972 B2DEBUG(10, "Could not load Datafield: " << p_extendedpts.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1973 iclock);
1974 continue;
1975 }
1976 B2LDataField_DNN p_etftime(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etftime"));
1977 if ((p_etftime.name != "None") && (p_etftime.data.size() == 0)) {
1978 B2DEBUG(10, "Could not load Datafield: " << p_etftime.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1979 iclock);
1980 continue;
1981 }
1982 B2LDataField_DNN p_etfcc(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etfcc"));
1983 if ((p_etfcc.name != "None") && (p_etfcc.data.size() == 0)) {
1984 B2DEBUG(10, "Could not load Datafield: " << p_etfcc.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1985 iclock);
1986 continue;
1987 }
1988 B2LDataField_DNN p_etfqual(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etfquality"));
1989 if ((p_etfqual.name != "None") && (p_etfqual.data.size() == 0)) {
1990 B2DEBUG(10, "Could not load Datafield: " << p_etfqual.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1991 iclock);
1992 continue;
1993 }
1994 B2LDataField_DNN p_etfval(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("etfvalid"));
1995 if ((p_etfval.name != "None") && (p_etfval.data.size() == 0)) {
1996 B2DEBUG(10, "Could not load Datafield: " << p_etfval.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
1997 iclock);
1998 continue;
1999 }
2000 B2LDataField_DNN p_nntgdl(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("nntgdl"));
2001 if ((p_nntgdl.name != "None") && (p_nntgdl.data.size() == 0)) {
2002 B2DEBUG(10, "Could not load Datafield: " << p_nntgdl.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
2003 iclock);
2004 continue;
2005 }
2006 B2LDataField_DNN p_sttgdl(bitsNN, iclock, iTracker, neurodb->getB2FormatLine("sttgdl"));
2007 if ((p_sttgdl.name != "None") && (p_sttgdl.data.size() == 0)) {
2008 B2DEBUG(10, "Could not load Datafield: " << p_sttgdl.name << " from bitstream. Maybe offset was out of bounds? clock: " <<
2009 iclock);
2010 continue;
2011 }
2012
2013 // B2LDataField (bitsNN, iclock, iTracker, neurodb->getB2FormatLine(""));
2014
2015 CDCTriggerTrack* track2D = nullptr;
2016 // decode stereo hits
2017 if (true) { // (p_nnenable.data == "1") {
2018 unsigned sln = 0;
2019 B2DEBUG(21, padright(" Stereos: ", 100));
2020 for (auto stereolayer : {p_tsf1, p_tsf3, p_tsf5, p_tsf7}) {
2021 if (stereolayer.name == "None") {
2022 B2ERROR("Error in CDCTriggerNeuroConfig Payload, position of stereo tsf could not be found!");
2023 continue;
2024 }
2025 std::string tsstr = " | ";
2026 for (unsigned iHit = 0; iHit < 10; ++iHit) {
2027 tsOut ts = (sim13dt) ? decodeTSHit_sim(stereolayer.data.substr(iHit * lenTS, lenTS),
2028 p_2dcc.data) : decodeTSHit(stereolayer.data.substr(iHit * lenTS, lenTS));
2029 extraHitTimeOut exTime = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
2030 if (stereolayer.data.size() % 87 == 0) {
2031 exTime = (sim13dt) ? decodeTSHitExtra_sim(stereolayer.data.substr(iHit * lenTS, lenTS),
2032 p_2dcc.data) : decodeTSHitExtra(stereolayer.data.substr(iHit * lenTS, lenTS));
2033 } //if it is full wire
2034 if (ts[3] > 0) { // if it is 0, it means 'no hit'
2035 unsigned iTS = TSIDInSL(ts[0], sln * 2 + 1, iTracker);
2036 tsstr += std::to_string(iTS) + ", " + std::to_string(ts[1]) + ", " + std::to_string(ts[2]) + ", " + std::to_string(ts[3]) + " | ";
2037 addTSHit(ts, sln * 2 + 1, iTracker, tsHitsAll, iclock, exTime);
2038 }
2039 }
2040 B2DEBUG(21, padright(" SL" + std::to_string(sln * 2 + 1) + tsstr, 100));
2041 ++sln;
2042 }
2043 }
2044 B2DEBUG(21, padright(" 2DCC: " + std::to_string(std::stoi(p_2dcc.data, 0, 2)) + ", (" + p_2dcc.data + ")", 100));
2045 B2DEBUG(21, padright(" ETFCC: " + std::to_string(std::stoi(p_etfcc.data, 0, 2)) + ", (" + p_etfcc.data + ")", 100));
2046 B2DEBUG(21, padright(" ETFVAL: " + std::to_string(std::stoi(p_etfval.data, 0, 2)) + ", (" + p_etfval.data + ")", 100));
2047 B2DEBUG(21, padright(" ETFT0: " + std::to_string(std::stoi(p_etftime.data, 0, 2)) + ", (" + p_etftime.data + ")", 100));
2048 B2DEBUG(21, padright(" ETFQuality: " + std::to_string(std::stoi(p_etfqual.data, 0, 2)) + ", (" + p_etfqual.data + ")", 100));
2049 if (p_nnenable.data == "1") {
2050 bool hasETFTime = false;
2051 if (p_etfval.data == "1") {
2052 storeETFTime->addBinnedEventT0(std::stoi(p_etftime.data, 0, 2), Const::CDC);
2053 hasETFTime = true;
2054 }
2055 std::vector<bool> foundoldtrack{false};
2056 std::vector<bool> driftthreshold{false};
2057 bool valstereobit;
2058 if (p_foundoldtrack.name != "None") {
2059 foundoldtrack = decodefoundoldtrack(p_foundoldtrack.data);
2060 }
2061 if (p_driftthreshold.name != "None") {
2062 driftthreshold = decodedriftthreshold(p_driftthreshold.data);
2063 }
2064 if (p_valstereobit.name != "None") {
2065 valstereobit = decodevalstereobit(p_valstereobit.data);
2066 }
2067
2068 if (std::all_of(p_phi.data.begin(), p_phi.data.end(), [](char i) {return i == 0;})) {
2069 B2ERROR("Empty Phi Value found for 2DTrack, should not happen!");
2070 continue;
2071 }
2072 TRG2DFinderTrack trk2D = decode2DTrack(
2073 "00", //charge
2074 p_omega.data,
2075 p_phi.data,
2076 p_ts0.data,
2077 p_ts2.data,
2078 p_ts4.data,
2079 p_ts6.data,
2080 p_ts8.data,
2081 iTracker,
2082 p_2dcc.data,
2083 sim13dt);
2084 track2D = store2DTracks->appendNew(trk2D.phi0, trk2D.omega, 0., foundoldtrack, driftthreshold, valstereobit, -1, iclock, iTracker);
2085 track2D->setRawOmega(trk2D.hwOmega);
2086 track2D->setRawPhi0(trk2D.hwPhi0);
2087 B2DEBUG(12, padright(" 2DTrack: (phi=" + std::to_string(trk2D.phi0) + ", omega=" + std::to_string(
2088 trk2D.omega) + ", update=" + std::to_string(foundoldtrack[1]) + ")", 100));
2089
2090 // add axial hits and create relations
2091 std::string tsstr;
2092 for (unsigned iAx = 0; iAx < nAxialTSF; ++iAx) {
2093 const auto& ts = trk2D.ts[iAx];
2094 if (ts[3] > 0) {
2095 CDCTriggerSegmentHit* hit =
2096 addTSHit(ts, 2 * iAx, iTracker, tsHits, iclock);
2097 unsigned iTS = TSIDInSL(ts[0], iAx * 2, iTracker);
2098 tsstr += "(SL" + std::to_string(iAx * 2) + ", " + std::to_string(iTS) + ", " + std::to_string(ts[1]) + ", " + std::to_string(
2099 ts[2]) + ", " + std::to_string(ts[3]) + "),";
2100 track2D->addRelationTo(hit);
2101 }
2102 }
2103 B2DEBUG(16, padright(" 2DTrack TS: " + tsstr, 100));
2104
2105
2106 if (track2D) {
2107 TRGNeuroTrack trkNN;
2108 trkNN = decodeDNNTrack(p_mlpout_z.data,
2109 p_mlpout_theta.data,
2110 p_mlpout_prob.data,
2111 p_tsfsel.data,
2112 p_mlpin_alpha.data,
2113 p_mlpin_drifttime.data,
2114 p_mlpin_id.data,
2115 p_mlpin_extratime.data,
2116 p_netsel.data,
2117 neurodb,
2118 p_2dcc.data,
2119 sim13dt,
2120 p_extendedpts);
2121
2122
2123 B2DEBUG(11, padright(" NNTrack: (z=" + std::to_string(trkNN.z) + ", theta=" + std::to_string(trkNN.theta) + ")", 100));
2124
2125 double phi0 = track2D->getPhi0();
2126 double omega = track2D->getOmega();
2127
2128 std::vector<unsigned> tsvector(9, 0);
2129 std::vector<unsigned> tstimevector(9, 0);
2130 tsstr = "";
2131 // turns false, as soon as there is a ts, which is not contained in the 2dfindertrack
2132 bool isin2d = true;
2133 for (unsigned iSL = 0; iSL < 9; ++iSL) {
2134 tsvector[iSL] = trkNN.ts[iSL][3];
2135 tstimevector[iSL] = trkNN.ts[iSL][1];
2136 if (trkNN.ts[iSL][3] > 0) {
2137 unsigned iTS = TSIDInSL(trkNN.ts[iSL][0], iSL, iTracker);
2138 tsstr += "(SL" + std::to_string(iSL) + ", " + std::to_string(iTS) + ", " + std::to_string(trkNN.ts[iSL][1]) + ", " + std::to_string(
2139 trkNN.ts[iSL][2]) + ", " + std::to_string(trkNN.ts[iSL][3]) + "),\n";
2140 // check, wether axials are a subset of 2dfinderTS:
2141 if (iSL % 2 == 0) {
2142 if (!(trk2D.ts[iSL / 2][0] == trkNN.ts[iSL][0] &&
2143 //trk2D.ts[iSL / 2][1] == trkNN.ts[iSL][1] &&
2144 trk2D.ts[iSL / 2][2] == trkNN.ts[iSL][2] &&
2145 trk2D.ts[iSL / 2][3] == trkNN.ts[iSL][3])) {
2146 isin2d = false;
2147 }
2148 }
2149
2150 } else {
2151 tsstr += "( - ),\n";
2152 }
2153 }
2154
2155 B2DEBUG(15, padright(" NNTrack TS: " + tsstr, 100));
2156
2157 CDCTriggerTrack* trackNN = storeNNTracks->appendNew(phi0, omega, 0.,
2158 trkNN.z, cos(trkNN.theta) / sin(trkNN.theta), trkNN.prob, 0., track2D->getFoundOldTrack(), track2D->getDriftThreshold(),
2159 track2D->getValidStereoBit(), trkNN.sector, tsvector, iclock, iTracker);
2160 trackNN->setHasETFTime(hasETFTime);
2161 track2D->setHasETFTime(hasETFTime);
2162 trackNN->setRawOmega(track2D->getRawOmega());
2163 trackNN->setRawPhi0(track2D->getRawPhi0());
2164 trackNN->setRawTheta(trkNN.hwTheta);
2165 trackNN->setRawZ(trkNN.hwZ);
2166 if (hasETFTime) {
2167 trackNN->setETF_unpacked(std::stoi(p_etftime.data, 0, 2));
2168 track2D->setETF_unpacked(std::stoi(p_etftime.data, 0, 2));
2169 }
2170 trackNN->setETF_recalced(recalcETF(p_mlpin_drifttime.data, tstimevector, trackNN));
2171 track2D->setETF_recalced(recalcETF(p_mlpin_drifttime.data, tstimevector, trackNN));
2172
2173 if (isin2d == false) {
2174 trackNN->setQualityVector(1);
2175 }
2176 std::vector<float> inputVector(71, 0.);
2177 std::vector<int> rawinputVector(71, 0.);
2178 int counts = 0;
2179 for (unsigned iSL = 0; iSL < 9; ++iSL) {
2180 inputVector[3 * iSL + counts] = trkNN.inputID[iSL];
2181 inputVector[3 * iSL + 1 + counts] = trkNN.inputT[iSL];
2182 inputVector[3 * iSL + 2 + counts] = trkNN.inputAlpha[iSL];
2183 rawinputVector[3 * iSL + counts] = trkNN.rawinputID[iSL];
2184 rawinputVector[3 * iSL + 1 + counts] = trkNN.rawinputT[iSL];
2185 rawinputVector[3 * iSL + 2 + counts] = trkNN.rawinputAlpha[iSL];
2186 if (iSL % 2 == 1) {
2187 counts += 11;
2188 }
2189 }
2190 for (unsigned iSL = 0; iSL < 4; ++iSL) {
2191 for (unsigned iwire = 0; iwire < 11; ++iwire) {
2192 inputVector[(iSL * (11 + 6) + iwire + 6)] = trkNN.inputExtraT[iSL][iwire];
2193 rawinputVector[(iSL * (11 + 6) + iwire + 6)] = trkNN.rawinputExtraT[iSL][iwire];
2194 }
2195 }
2196 trackNN->setRawInput(rawinputVector);
2197
2198 CDCTriggerMLPInput* storeInput =
2199 storeNNInputs->appendNew(inputVector, trkNN.sector);
2200 trackNN->addRelationTo(storeInput);
2201 track2D->addRelationTo(trackNN);
2202
2203 for (unsigned iSL = 0; iSL < 9; ++iSL) {
2204 if (trkNN.ts[iSL][3] > 0) {
2205 CDCTriggerSegmentHit* hit = nullptr;
2206 // if (sim13dt) {
2207 // // get extended priority time for stereos from the allstereots storearray
2208 // for (int ihit = 0; ihit<tsHitsAll->getEntries(); ++ihit) {
2209 // CDCTriggerSegmentHit* compare = (*tsHitsAll)[ihit];
2210 // if (compare->getISuperLayer() == iSL &&
2211 // compare->getIWireCenter() == TSIDInSL(trkNN.ts[iSL][0], iSL, iTracker) &&
2212 // compare->getPriorityPosition() == trkNN.ts[iSL][3] &&
2213 // compare->getLeftRight() == trkNN.ts[iSL][2] ) {
2214 // hit = compare;
2215 // }
2216 // }
2217 // if (!(!hit)) {
2218 // tsHits->appendNew(hit->getISuperLayer(), hit->getIWireCenter(), hit->getPriorityPosition(), hit->getLeftRight(), hit->priorityTime(), 0, hit->foundTime(), iTracker);
2219 // }
2220 // // get the extended pt for axials from the already existing 2d TS
2221 // for (int ihit = 0; ihit<tsHits->getEntries(); ++ihit) {
2222 // CDCTriggerSegmentHit* compare = (*tsHits)[ihit];
2223 // if (compare->getISuperLayer() == iSL &&
2224 // compare->getIWireCenter() == TSIDInSL(trkNN.ts[iSL][0], iSL, iTracker) &&
2225 // compare->getPriorityPosition() == trkNN.ts[iSL][3] &&
2226 // compare->getLeftRight() == trkNN.ts[iSL][2] ) {
2227 // hit = compare;
2228 // }
2229 // }
2230
2231 // }
2232
2233 // cppcheck-suppress knownConditionTrueFalse
2234 if (!hit) {
2235 hit = addTSHit(trkNN.ts[iSL], iSL, iTracker, tsHits, iclock, trkNN.TSExtraT[iSL]);
2236 // B2DEBUG(1, "Hit with short drift time added, should not happen!");
2237 // }
2238 }
2239 trackNN->addRelationTo(hit);
2240 if (iSL % 2 == 0) {
2241 track2D->addRelationTo(hit);
2242 }
2243 }
2244 }
2245 if (p_nntgdl.name != "None") {
2246 bool dbool = decodebool(p_nntgdl.data);
2247 trackNN->setNNTToGDL(dbool);
2248 B2DEBUG(20, "NNT to GDL Bit decision for this track is: " << dbool);
2249 }
2250 if (p_sttgdl.name != "None") {
2251 bool dbool = decodebool(p_sttgdl.data);
2252 trackNN->setSTTToGDL(dbool);
2253 B2DEBUG(20, "STT to GDL Bit decision for this track is: " << dbool);
2254 }
2255
2256 }
2257
2258
2259 //
2260 // B2DEBUG(15, "bits for foundoldtrack: ");
2261 // for (auto x : foundoldtrack) {
2262 // B2DEBUG(15, x);
2263 // }
2264 // B2DEBUG(15, "bits for driftthreshold: ");
2265 // for (auto x : driftthreshold) {
2266 // B2DEBUG(15, x);
2267 // }
2268 // B2DEBUG(15, "bits for valstereobit: " << valstereobit);
2269 // B2DEBUG(15, "make new 2D track with phi " << trk2D.phi0 << " omega " << trk2D.omega << " clock " << iclock);
2270
2271 }
2272 }
2273 }
2274 }
2275
2276 void decodeNNIO_old(
2277 StoreArray<CDCTriggerUnpacker::NNBitStream>* bitsNN,
2278 StoreArray<CDCTriggerTrack>* store2DTracks,
2279 StoreArray<CDCTriggerTrack>* storeNNTracks,
2280 StoreArray<CDCTriggerSegmentHit>* tsHits,
2281 StoreArray<CDCTriggerMLPInput>* storeNNInputs)
2282 {
2283 for (short iclock = 0; iclock < bitsNN->getEntries(); ++iclock) {
2284 NNBitStream* bitsIn = (*bitsNN)[iclock];
2285 NNBitStream* bitsOutEnable = (*bitsNN)[iclock];
2286 for (unsigned iTracker = 0; iTracker < nTrackers; ++iTracker) {
2287 const auto slvOutEnable = bitsOutEnable->signal()[iTracker];
2288 const auto slvIn = bitsIn->signal()[iTracker];
2289 std::string stringOutEnable = slv_to_bin_string(slvOutEnable); //.substr(NN_OUT_WIDTH - 570, NN_OUT_WIDTH);
2290 std::string stringIn = slv_to_bin_string(slvIn); //.substr(NN_OUT_WIDTH - 570, NN_OUT_WIDTH);
2291 if (stringOutEnable.c_str()[0] == '1') {
2292 CDCTriggerTrack* nntrack2D = decodeNNInput(iclock, iTracker, bitsIn, store2DTracks, tsHits);
2293 if (nntrack2D) {
2294 int foundTime = iclock;
2295 if (foundTime < bitsNN->getEntries()) {
2296 NNBitStream* bitsOut = (*bitsNN)[foundTime];
2297 NNBitStream* bitsSelectTS = (*bitsNN)[iclock];
2298 decodeNNOutput_old(iclock, iTracker, bitsOut, bitsSelectTS,
2299 storeNNTracks, tsHits, storeNNInputs,
2300 nntrack2D);
2301 }
2302 }
2303 }
2304 }
2305 }
2306 }
2307 }
2309}
const SignalBus & signal()
accessors
Definition Bitstream.h:72
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::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:270
int hwZ
raw output values of hw network
Definition Unpacker.h:301
std::array< float, 9 > inputT
input T list of a NN track
Definition Unpacker.h:289
std::array< float, 9 > inputAlpha
input Alpha list of a NN track
Definition Unpacker.h:292
unsigned sector
sector of a NN track
Definition Unpacker.h:282
std::array< std::array< float, 11 >, 4 > inputExtraT
input extra time list of a NN track
Definition Unpacker.h:295
double prob
probability of background
Definition Unpacker.h:284
std::array< float, 9 > inputID
input ID list of a NN track
Definition Unpacker.h:286
std::array< tsOut, 9 > ts
input TS list of a NN track
Definition Unpacker.h:298
double theta
theta of a NN track
Definition Unpacker.h:280