Belle II Software  release-05-01-25
PXDReadRawBonnDAQMatched.cc
1 //+
2 // File : PXDReadRawBonnDAQMatched.cc
3 // Description : Module to Load Raw PXD Data from DHH network-dump file and store it as RawPXD in Data Store
4 // This is meant for lab use (standalone testing, debugging) without an event builder.
5 // This module is able to read the BonnDAQ data unordered, e.g. scan for the current event number
6 //
7 // Author : Bjoern Spruck
8 // Date : 16.06.2019
9 //-
10 
11 #include <pxd/modules/pxdUnpacking/PXDReadRawBonnDAQMatched.h>
12 #include <boost/spirit/home/support/detail/endian.hpp>
13 #include <boost/crc.hpp>
14 
15 using namespace std;
16 using namespace Belle2;
17 using namespace PXD;
18 
19 using namespace boost::spirit::endian;
20 
21 using boost::crc_optimal;
22 typedef crc_optimal<32, 0x04C11DB7, 0, 0, false, false> dhe_crc_32_type;
23 
24 //-----------------------------------------------------------------
25 // Register the Module
26 //-----------------------------------------------------------------
27 REG_MODULE(PXDReadRawBonnDAQMatched)
28 
29 //-----------------------------------------------------------------
30 // Implementation
31 //-----------------------------------------------------------------
32 
34 {
35  fh = 0;
36  //Set module properties
37  setDescription("Read a BonnDAQ form file, match to current event and stores it as RawPXD in Data Store");
38  //setPropertyFlags( c_ParallelProcessingCertified); // can not be run in parallel!
39 
40  addParam("RawPXDsName", m_RawPXDsName, "The name of the StoreArray of RawPXDs to be written", std::string(""));
41 
42  addParam("FileName", m_filename, "file name");
43  m_buffer = new int[MAXEVTSIZE];
44 
45  B2DEBUG(29, "PXDReadRawBonnDAQMatchedModule: Constructor done.");
46 }
47 
48 
49 PXDReadRawBonnDAQMatchedModule::~PXDReadRawBonnDAQMatchedModule()
50 {
51  delete[] m_buffer;
52 }
53 
54 void PXDReadRawBonnDAQMatchedModule::initialize()
55 {
56  // Open File
57  fh = fopen(m_filename.c_str(), "rb");
58  if (fh) {
59  B2INFO("Read BonnDAQ Data from " << m_filename);
60  } else {
61  B2ERROR("Could not open BonnDAQ Data: " << m_filename);
62  }
63 
64  // Ask EvtMetaData
65  m_eventMetaDataPtr.isRequired();
66  // Register RawPXD
67  m_rawPXD.registerInDataStore(m_RawPXDsName, DataStore::EStoreFlags::c_ErrorIfAlreadyRegistered);
68 
69  B2DEBUG(29, "PXDReadRawBonnDAQMatchedModule: initialized.");
70 }
71 
72 int PXDReadRawBonnDAQMatchedModule::read_data(char* data, size_t len)
73 {
74  size_t l = 0;
75  if (fh) l = fread(data, 1, len, fh);
76  if (l != len) return 0;
77  return l;
78 }
79 
80 int PXDReadRawBonnDAQMatchedModule::readOneEvent(unsigned int& rettriggernr)
81 {
82  unsigned int triggernr = 0xFFFFFFFF;
83 
84  auto current_offset = ftell(fh);
85  if (current_offset > m_last_offset) m_last_offset = current_offset;
86 
87  struct EvtHeader {
88  ulittle16_t size;
89  ulittle16_t header;
90  unsigned int get_size(void) { return (unsigned int) size + (((unsigned int)(header & 0x000F)) << 16);};
91  unsigned int get_size_group(void) { return (unsigned int) size + (((unsigned int)((header & 0x003F) ^ 0x0020)) << 16);};
92  unsigned int get_header12(void) { return (header & 0xFFF0);};
93  unsigned int get_header10(void) { return (header & 0xFFC0);};
94  unsigned int get_header8(void) { return (header & 0xFF00);};
95  };
96 
97  char* data = (char*)m_buffer;
98  struct EvtHeader* evt = (struct EvtHeader*)data;
99 
100  while (1) {
101  ulittle32_t* data32 = (ulittle32_t*)data;
102  ulittle16_t* data16 = (ulittle16_t*)data;
103  // Read 8 bytes header (group)
104  int br = read_data(data, 4);
105  if (br <= 0) return br;
106  unsigned int chunk_size = 0;
107  if (evt->get_header8() == 0) {
108  B2DEBUG(29, "Group Header $" << std::hex << evt->get_header10() << " Chunk size " << std::dec << evt->get_size());
109  chunk_size = evt->get_size_group();
110  } else {
111  B2DEBUG(29, "Header $" << std::hex << evt->get_header12() << " Chunk size " << std::dec << evt->get_size());
112  chunk_size = evt->get_size();
113  }
114  if (chunk_size <= 1) return 0;
115  br = read_data(data + 4, chunk_size * 4 - 4);
116  if (br <= 0) return br;
117  if (evt->get_header12() == 0xe230) {
118  B2DEBUG(29, "File info " << std::hex << evt->get_header12() << " Events " << std::dec << data32[1]);
119  continue;
120  } else if (evt->get_header12() == 0xe100) {
121  B2DEBUG(29, "Info Event " << std::hex << evt->get_header12() << " RunNr $" << std::hex << data32[1]);
122  // if (m_runNr == 0) m_runNr = data32[1]; // we assume it will not change within one file
123  continue;
124  } else if (evt->get_header10() == 0x0000) { // war 0x0020
125  B2DEBUG(29, "Run Event Group " << std::hex << evt->get_header10() << " Magic $" << std::hex << data32[1]);
126  continue;
127  } else if (evt->get_header12() == 0xbb00) {
128  B2DEBUG(29, "Run Event " << std::hex << evt->get_header12() << " Magic $" << std::hex << data32[1]);
129  continue;
130  } else if (evt->get_header10() == 0x0080) { // war 0x00A0
131  int togo = chunk_size;
132  B2DEBUG(29, "Data Event Group " << std::hex << evt->get_header10() << " TriggerNr $" << std::hex << data32[1]);
133  triggernr = data32[1];
134  togo -= 2;
135  data32 += 2;
136  data16 += 4;
137  while (togo > 2) {
138  B2DEBUG(29, "TOGO: " << togo);
139  B2DEBUG(29, " ............... " << std::hex << data32[0] << " TriggerNr $" << std::hex << data32[1]);
140  if (triggernr != data32[1]) B2ERROR("Trigger Nr does not match!");
141  B2DEBUG(29, " ............... " << std::hex << data32[2]);
142  togo -= 2;
143  data32 += 2;
144  data16 += 4;
145  if ((data32[0] & 0xFFFF0000) == 0xCAFE0000) {
146  int frames = (data32[0] & 0x3FF);
147  B2DEBUG(29, "Frames: " << frames);
148  int size = 0;
149  bool nocrc = (data32[0] & 0x8000) != 0;
150 
151  if ((data32[0] & 0x4000) == 0) B2FATAL("large data fields not supported");
152 
153  togo--;
154  data32++;
155  data16 += 2;
157  std::vector <unsigned int> m_onsen_header;
158 
160  std::vector <std::vector <unsigned char>> m_onsen_payload;
161  int offset = ((frames + 1) & ~1);
162 
163  ulittle16_t* table16 = data16;
164  if (!nocrc) {
165  togo--; // jump over TOC CRC
166  data32++;
167  data16 += 2;
168  }
169 
170  for (int i = 0; i < frames; i++) {
171  // B2INFO(".... " << i << ": " << table16[i]);
172  size += table16[i];
173 
175  std::vector <unsigned char> m_current_frame;
176 
177  for (int j = 0; j < (int)table16[i] * 2; j++) {
178  unsigned short w = data16[offset++];
179  m_current_frame.push_back((unsigned char)(w >> 8));
180  m_current_frame.push_back((unsigned char)(w));
181  }
182 
183  if (nocrc) { // recalculate
184  dhe_crc_32_type current_crc;
185  current_crc.process_bytes(m_current_frame.data(), m_current_frame.size());
186  unsigned int w = current_crc.checksum();
187  m_current_frame.push_back((unsigned char)(w >> 24));
188  m_current_frame.push_back((unsigned char)(w >> 16));
189  m_current_frame.push_back((unsigned char)(w >> 8));
190  m_current_frame.push_back((unsigned char)(w));
191  }
192 
193  m_onsen_header.push_back(m_current_frame.size());
194  m_onsen_payload.push_back(m_current_frame);
195  }
196  togo -= ((frames + 1) & ~1) / 2 + size;
197  data32 += ((frames + 1) & ~1) / 2 + size;
198  data16 += ((frames + 1) & ~1) + size * 2;
199 
200  if (nocrc) {
201  togo--;
202  data32++;
203  data16 += 2;
204  }
205 
206  if (rettriggernr == triggernr) m_rawPXD.appendNew(m_onsen_header, m_onsen_payload);
207  }
208  }// while ...
209 
210  rettriggernr = triggernr;
211 
212  m_event_offset[triggernr] = current_offset;
213  current_offset = ftell(fh);
214  if (current_offset > m_last_offset) m_last_offset = current_offset;
215 
216  return 1;
217  } else {
218  B2ERROR("Undefine Header $" << std::hex << evt->get_header12());
219  continue;
220  }
221  continue;
222 
223  }
224  rettriggernr = 0xFFFFFFFF;
225 
226  return 0;
227 }
228 
229 void PXDReadRawBonnDAQMatchedModule::event()
230 {
231  if (fh == 0) {
232  B2ERROR("Unexpected close of bonndaq file.");
233  terminate();
234  return;
235  }
236 
237  auto triggernr = m_eventMetaDataPtr->getEvent();
238 
239  // Check if event has an offset, if not skip until end of checked area
240  auto offset = m_event_offset[triggernr];
241  if (offset == 0) offset = m_last_offset;
242  fseek(fh, offset, SEEK_SET);
243  // Get a record from file
244  auto tnr = triggernr;
245  do {
246  // Search for triggernr
247  tnr = triggernr; // set again as it is the return value
248  int stat = readOneEvent(tnr);
249  if (stat <= 0) {
250  // End of File
251  break;
252  };
253  } while (tnr != triggernr); // found and filled, else continue
254 
255  // set return value to true only if matching event was found
256  setReturnValue(tnr == triggernr);
257 
258  return;
259 }
260 
261 void PXDReadRawBonnDAQMatchedModule::terminate()
262 {
263  if (fh) fclose(fh);
264  fh = 0;
265 }
266 
Belle2::PXD::PXDReadRawBonnDAQMatchedModule
Module to Load BonnDAQ file and store it as RawPXD in Data Store This is meant for lab use (standalon...
Definition: PXDReadRawBonnDAQMatched.h:36
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2::EvtHeader
Header structure of streamed object list.
Definition: EvtMessage.h:29
Belle2::Module
Base class for Modules.
Definition: Module.h:74
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19