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