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