Belle II Software  release-05-02-19
ARICHPackerModule.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2010 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Luka Santelj *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 // Own include
12 #include <arich/modules/arichPacker/ARICHPackerModule.h>
13 
14 // framework - DataStore
15 #include <framework/datastore/StoreArray.h>
16 #include <framework/datastore/StoreObjPtr.h>
17 
18 // framework aux
19 #include <framework/logging/Logger.h>
20 
21 // Dataobject classes
22 #include <arich/dataobjects/ARICHDigit.h>
23 #include <rawdata/dataobjects/RawARICH.h>
24 #include <framework/dataobjects/EventMetaData.h>
25 #include <bitset>
26 
27 using namespace std;
28 
29 namespace Belle2 {
35 #define ARICH_BUFFER_NWORDS 252 // arich number of words (ints) in buffer; 3 + 33 + 6 * 36; 3 merger header words + 5.5 FEB header words / FEB + 36 data words per / FEB
36  //-----------------------------------------------------------------
37  // Register module
38  //-----------------------------------------------------------------
39 
40  REG_MODULE(ARICHPacker)
41 
42  //-----------------------------------------------------------------
43  // Implementation
44  //-----------------------------------------------------------------
45 
47  m_nonSuppressed(0), m_bitMask(0), m_debug(0)
48 
49  {
50  // set module description (e.g. insert text)
51  setDescription("Raw data packer for ARICH");
52  setPropertyFlags(c_ParallelProcessingCertified);
53  addParam("nonSuppressed", m_nonSuppressed, "Pack in non-suppressed format (store all channels)", unsigned(0));
54  addParam("version", m_version, "dataformat version", unsigned(6));
55  addParam("bitMask", m_bitMask, "hit bit mask (4 bits/channel)", (unsigned)0xF);
56  addParam("debug", m_debug, "print packed bitmap", 0);
57  addParam("inputDigitsName", m_inputDigitsName, "name of ARICHDigit store array", string(""));
58  addParam("outputRawDataName", m_outputRawDataName, "name of RawARICH store array", string(""));
59 
60  }
61 
62  ARICHPackerModule::~ARICHPackerModule()
63  {
64  }
65 
66  void ARICHPackerModule::initialize()
67  {
68 
69  StoreArray<ARICHDigit> digits(m_inputDigitsName);
70  digits.isRequired();
71 
72  StoreArray<RawARICH> rawData(m_outputRawDataName);
73  rawData.registerInDataStore();
74  }
75 
76  void ARICHPackerModule::beginRun()
77  {
78  }
79 
80  void ARICHPackerModule::event()
81  {
82 
83  StoreObjPtr<EventMetaData> evtMetaData;
84  StoreArray<ARICHDigit> digits(m_inputDigitsName);
85  StoreArray<RawARICH> rawData(m_outputRawDataName);
86 
87  int nModules = N_MERGERS * N_FEB2MERGER;
88 
89  vector<const ARICHDigit*>* sortedDigits = new vector<const ARICHDigit*>[nModules];
90  int nPacked = 0;
91  for (const auto& digit : digits) {
92  int moduleID = digit.getModuleID();
93  unsigned mergerID = m_mergerMap->getMergerID(moduleID);
94  if (!mergerID) { B2WARNING("No module2merger mapping for module ID: " << moduleID << "; Digit will not be packed!"); continue;}
95  if (!m_copperMap->getCopperID(mergerID)) { B2WARNING("No merger2copper mapping for merger ID: " << mergerID << "; Digit will not be packed!"); continue;}
96  sortedDigits[moduleID - 1].push_back(&digit);
97  nPacked++;
98  }
99 
100  int buffer[4][ARICH_BUFFER_NWORDS];
101 
102  for (const auto& copperID : m_copperMap->getCopperIDs()) {
103 
104  int bufferSize[4] = {0, 0, 0, 0};
105  for (int finesse = 0; finesse < 4; finesse++) {
106 
107  unsigned ibyte = 0;
108 
109  for (int j = 0; j < ARICH_BUFFER_NWORDS; j++) {
110  buffer[finesse][j] = 0;
111  }
112 
113  auto* buf = buffer[finesse];
114 
115  // get corresponding merger ID
116  unsigned mergerID = m_copperMap->getMergerID(copperID, finesse);
117  unsigned mergerSN = m_mergerMap->getMergerSN(mergerID);
118  if (!mergerID) continue;
119 
120  ARICHRawHeader mergerHead;
121  unsigned dataFormat = m_nonSuppressed + 1; // production data -> TODO: use enum
122  mergerHead.type = dataFormat;
123  mergerHead.version = m_version;
124  mergerHead.mergerID = mergerSN;
125  mergerHead.FEBSlot = 0;
126  mergerHead.trigger = evtMetaData->getEvent();
127  // mergerHead.length dont forget
128 
129  ibyte += ARICHRAW_HEADER_SIZE;
130 
131  int nboards = N_FEB2MERGER;
132 
133  for (int k = 0; k < nboards; k++) {
134 
135  int moduleID = m_mergerMap->getModuleID(mergerID, k + 1);
136  if (moduleID <= 0) continue;
137 
138  // FEB header
139  ARICHRawHeader FEBHead;
140  FEBHead.type = dataFormat;
141  FEBHead.version = m_version;
142  FEBHead.mergerID = mergerSN;
143  FEBHead.FEBSlot = k; // board slots go from 0-5 for now, if firmware is updated to 1-6 add +1 !!
144  FEBHead.trigger = evtMetaData->getEvent();
145 
146  if (m_nonSuppressed) {
147  // data length in bytes
148  FEBHead.length = 144 + ARICHFEB_HEADER_SIZE; // 144ch * 1 byte
149  writeHeader(buf, ibyte, FEBHead);
150  ibyte += ARICHFEB_HEADER_SIZE; // leave slot for FEB header (FEB header to be implemented!)
151 
152  // write data
153  for (const auto& digit : sortedDigits[moduleID - 1]) {
154  unsigned chn = digit->getChannelID();
155  //std::cout << "pack: mod: " << boardID << " ch " << chn<< std::endl;
156  unsigned shift = 143 - chn;
157  unsigned bitmap = (unsigned)digit->getBitmap();
158  buf[(ibyte + shift) / 4] += (bitmap << (3 - (ibyte + shift) % 4) * 8);
159  }
160  ibyte += 144;
161  } else {
162  FEBHead.length = ARICHFEB_HEADER_SIZE + sortedDigits[moduleID - 1].size() * 2; // each hit is 2 bytes! channel + bitmap
163  writeHeader(buf, ibyte, FEBHead);
164  ibyte += ARICHFEB_HEADER_SIZE; // leave slot for FEB header (FEB header to be implemented!)
165 
166  for (const auto& digit : sortedDigits[moduleID - 1]) {
167  unsigned chn = digit->getChannelID();
168  //std::cout << "pack: mod: " << boardID << " ch " << chn<< std::endl;
169  unsigned shift = (3 - ibyte % 4) * 8;
170  buf[ibyte / 4] += (chn << shift);
171  ibyte++;
172  shift = (3 - ibyte % 4) * 8;
173  unsigned bitmap = (unsigned)digit->getBitmap();
174  buf[ibyte / 4] += (bitmap << shift);
175  ibyte++;
176  }
177  }
178  }
179 
180  unsigned merg = 0;
181  mergerHead.length = ibyte - ARICHRAW_HEADER_SIZE;
182  writeHeader(buf, merg, mergerHead);
183 
184  bufferSize[finesse] = ceil(ibyte / 4.);
185 
186  if (m_debug) {
187  std::cout << "Pack finesse: " << finesse << std::endl;
188  for (int i = 0; i < bufferSize[finesse]; i++) {
189  std::cout << i << "-th word bitset " << bitset<32>(buf[i]) << std::endl;
190  }
191  }
192  }
193 
194  RawCOPPERPackerInfo info;
195  info.exp_num = evtMetaData->getExperiment();
196  info.run_subrun_num = (evtMetaData->getRun() << 8) +
197  (evtMetaData->getSubrun() & 0xFF); // run number : 14bits, subrun # : 8bits
198  info.eve_num = evtMetaData->getEvent();
199  info.node_id = ARICH_ID + copperID;
200  info.tt_ctime = 0;
201  info.tt_utime = 0;
202  info.b2l_ctime = 0;
203  info.hslb_crc16_error_bit = 0;
204  info.truncation_mask = 0;
205  info.type_of_data = 0;
206 
207  auto* raw = rawData.appendNew();
208  raw->PackDetectorBuf(buffer[0], bufferSize[0],
209  buffer[1], bufferSize[1],
210  buffer[2], bufferSize[2],
211  buffer[3], bufferSize[3],
212  info);
213 
214  }
215 
216  delete [] sortedDigits;
217 
218  }
219 
220  void ARICHPackerModule::writeHeader(int* buffer, unsigned& ibyte, const ARICHRawHeader& head)
221  {
222 
223  unsigned char line1[4];
224  int shift;
225 
226  line1[3] = head.type;
227  line1[2] = head.version;
228  line1[1] = head.mergerID;
229  line1[0] = head.FEBSlot;
230 
231  for (int i = 0; i < 4; i++) {
232  shift = (3 - ibyte % 4) * 8;
233  buffer[ibyte / 4] |= line1[3 - i] << shift;
234  ibyte++;
235  }
236 
237  unsigned char* len = (unsigned char*)&head.length;
238  for (int i = 0; i < 4; i++) {
239  shift = (3 - ibyte % 4) * 8;
240  buffer[ibyte / 4] |= len[3 - i] << shift;
241  ibyte++;
242  }
243 
244  // trigger number
245  unsigned char* trg = (unsigned char*)(&head.trigger);
246  for (int i = 0; i < 4; i++) {
247  shift = (3 - ibyte % 4) * 8;
248  buffer[ibyte / 4] |= trg[3 - i] << shift;
249  ibyte++;
250  }
251 
252  }
253 
254 
255 
256 
257  void ARICHPackerModule::endRun()
258  {
259  }
260 
261  void ARICHPackerModule::terminate()
262  {
263  }
264 
265 
267 } // end Belle2 namespace
268 
Belle2::StoreArray::appendNew
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:256
Belle2::RawCOPPERPackerInfo
struct to contain header information used by RawCOPPERFormat::Packer()
Definition: RawCOPPERPackerInfo.h:12
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2::ARICHPackerModule
Raw data packer for ARICH.
Definition: ARICHPackerModule.h:44
Belle2::Module
Base class for Modules.
Definition: Module.h:74
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::StoreObjPtr
Type-safe access to single objects in the data store.
Definition: ParticleList.h:33
Belle2::StoreArray
Accessor to arrays stored in the data store.
Definition: ECLMatchingPerformanceExpertModule.h:33
Belle2::ARICHRawHeader
Definition: ARICHRawDataHeader.h:17