Belle II Software  release-08-01-10
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 
26 namespace 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>;
257  double omega;
259  double phi0;
261  tsOutArray ts;
262  // hw values of 2dtrack
263  int hwOmega{0};
264  int hwPhi0{0};
265  };
267  struct TRGNeuroTrack {
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  };
289  struct B2LDataField {
290  B2LDataField(
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://confluence.desy.de/download/attachments/34033650/output-def.pdf
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://confluence.desy.de/download/attachments/34033650/output-def.pdf
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:686
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
static const double realNaN
constant for double NaN
double atan(double a)
atan for double
Definition: beamHelpers.h:34
Abstract base class for different kinds of events.
const char one_val
'1' in XSI VHDL simulation
Definition: Cosim.h:43
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::bitset< max - min+1 > subset(std::bitset< nbits > set)
extract a subset of bitstring, like substring.
Definition: Cosim.h:120
const char zero_val
'0' in XSI VHDL simulation
Definition: Cosim.h:45
std::string slv_to_bin_string(std::array< char, N > signal, bool padding=false)
Transform into string.
Definition: Cosim.h:64
void display_hex(const std::array< char, N > &signal)
Display signal in hex.
Definition: Cosim.h:81
std::string display_value(const char *count, int size)
Display value of the signal.
Definition: Cosim.h:48
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