Belle II Software development
SVDUnpackerDQMModule.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 "svd/modules/svdDQM/SVDUnpackerDQMModule.h"
10#include <svd/online/SVDOnlineToOfflineMap.h>
11
12#include <framework/datastore/StoreObjPtr.h>
13#include <framework/datastore/StoreArray.h>
14
15#include <svd/dataobjects/SVDDAQDiagnostic.h>
16
17#include <TDirectory.h>
18#include <TLine.h>
19#include <TStyle.h>
20
21#include <algorithm>
22#include <string>
23
24
25using namespace std;
26using namespace Belle2;
27
28//-----------------------------------------------------------------
29// Register the Module
30//-----------------------------------------------------------------
31REG_MODULE(SVDUnpackerDQM);
32
33
34//-----------------------------------------------------------------
35// Implementation
36//-----------------------------------------------------------------
37
38std::string SVDUnpackerDQMModule::m_xmlFileName = std::string("SVDChannelMapping.xml");
39
41{
42 //Set module properties
43 setDescription("DQM Histogram of the SVD Raw Data format.");
44
45 addParam("histogramDirectoryName", m_histogramDirectoryName, "Name of the directory where histograms will be placed.",
46 std::string("SVDUnpacker"));
47 addParam("DAQDiagnostics", m_SVDDAQDiagnosticsName, "Name of DAQDiagnostics Store Array.", std::string(""));
48 addParam("EventInfo", m_SVDEventInfoName, "Name of SVDEventInfo object.", std::string(""));
49
50 setPropertyFlags(c_ParallelProcessingCertified); // specify this flag if you need parallel processing
51}
52
53
54SVDUnpackerDQMModule::~SVDUnpackerDQMModule()
55{
56}
57
58//------------------------------------------------------------------
59// Function to define histograms
60//-----------------------------------------------------------------
61
63{
64
65 // Create a separate histogram directories and cd into it.
66 TDirectory* oldDir = gDirectory;
67 if (m_histogramDirectoryName != "") {
68 oldDir->mkdir(m_histogramDirectoryName.c_str());// do not use return value with ->cd(), its ZERO if dir already exists
69 oldDir->cd(m_histogramDirectoryName.c_str());
70 }
71
72 const unsigned short Bins_FTBFlags = 5;
73 const unsigned short Bins_FTBError = 4;
74 const unsigned short Bins_APVError = 4;
75 const unsigned short Bins_APVMatch = 1;
76 const unsigned short Bins_FADCMatch = 1;
77 const unsigned short Bins_UpsetAPV = 1;
78 const unsigned short Bins_BadMapping = 1;
79 const unsigned short Bins_BadHeader = 1;
80 const unsigned short Bins_MissedTrailer = 1;
81 const unsigned short Bins_MissedHeader = 1;
82 const unsigned short Bins_SEURecoData = 1;
83
84
85 const unsigned short nBins = Bins_FTBFlags + Bins_FTBError + Bins_APVError + Bins_APVMatch + Bins_FADCMatch + Bins_UpsetAPV +
86 Bins_BadMapping + Bins_BadHeader + Bins_MissedTrailer + Bins_MissedHeader + Bins_SEURecoData;
87
88 m_DQMUnpackerHisto = new TH2F("DQMUnpackerHisto", "SVD Data Format Monitor", nBins, 1, nBins + 1, 52, 1, 53);
89 m_DQMErrorEventsHisto = new TH1F("DQMErrorEventsHisto", "SVD Errors Event Counter", 4, 0, 4);
90 m_DQMSeuRecoveryFADCsEventHisto = new TH1F("DQMSeuRecoveryFADCsEventHisto", "Number of FADCs with SEURecovery", 53, 0, 53);
91 m_DQMnSamplesHisto = new TH2F("DQMnSamplesHisto", "nAPVsamples VS DAQMode", 3, 1, 4, 2, 1, 3);
92 m_DQMnSamplesHisto2 = new TH2F("DQMnSamplesHisto2", "nAPVsamples VS DAQMode", 2, 1, 3, 2, 1, 3);
93 m_DQMtrgQuality = new TH2F("DQMtrgQuality", "nAPVsamples VS trgQuality", 4, 1, 5, 2, 1, 3);
94
95 m_SEUonSensors = new SVDSummaryPlots("SEURecoOnSensors@view",
96 "SVD SEU (errAPV or errDET or errSYNC) detected on Sensors for the @view/@side");
97
98 m_DQMUnpackerHisto->GetYaxis()->SetTitle("FADC board");
99 m_DQMUnpackerHisto->GetYaxis()->SetTitleOffset(1.2);
100
101 m_DQMErrorEventsHisto->GetYaxis()->SetTitle("# of Events");
102 m_DQMErrorEventsHisto->GetYaxis()->SetTitleOffset(1.5);
103 m_DQMErrorEventsHisto->SetMinimum(0.7);
104
105 m_DQMSeuRecoveryFADCsEventHisto->GetYaxis()->SetTitle("# of Events");
106 m_DQMSeuRecoveryFADCsEventHisto->GetYaxis()->SetTitleOffset(1.5);
107 m_DQMSeuRecoveryFADCsEventHisto->SetMinimum(0.7);
108 m_DQMSeuRecoveryFADCsEventHisto->SetMaximum(1.0);
109
110 m_DQMnSamplesHisto->GetXaxis()->SetTitle("DAQ Mode");
111 m_DQMnSamplesHisto->GetYaxis()->SetTitle("number of APV samples");
112
113 m_DQMnSamplesHisto2->GetXaxis()->SetTitle("DAQ Mode");
114 m_DQMnSamplesHisto2->GetYaxis()->SetTitle("number of APV samples");
115
116 m_DQMtrgQuality->GetXaxis()->SetTitle("TRG Quality");
117 m_DQMtrgQuality->GetYaxis()->SetTitle("number of APV samples");
118
119 TString Xlabels[nBins] = {"EvTooLong", "TimeOut", "doubleHead", "badEvt", "errCRC", "badFADC", "badTTD", "badFTB", "badALL", "errAPV", "errDET", "errFrame", "errFIFO", "APVmatch", "FADCmatch", "errSYNC", "EVTmatch", "missHead", "missTrail", "badMapping", "SEURecovery"};
120
121 TString Ysamples[2] = {"3", "6"};
122 TString Xsamples[3] = {"3 samples", "6 samples", "3/6 mixed"};
123
124 TString Xquality[4] = {"coarse", "fine", "super fine", "no TRGSummary"};
125
126 //preparing X axis of the DQMUnpacker histograms
127 for (unsigned short i = 0; i < nBins; i++) m_DQMUnpackerHisto->GetXaxis()->SetBinLabel(i + 1, Xlabels[i].Data());
128
129 //preparing X and Y axis of the DQMnSamples histograms
130 for (unsigned short i = 0; i < 3; i++) m_DQMnSamplesHisto->GetXaxis()->SetBinLabel(i + 1, Xsamples[i].Data());
131 for (unsigned short i = 0; i < 2; i++) m_DQMnSamplesHisto2->GetXaxis()->SetBinLabel(i + 1, Xsamples[i].Data());
132
133 for (unsigned short i = 0; i < 2; i++) m_DQMnSamplesHisto->GetYaxis()->SetBinLabel(i + 1, Ysamples[i].Data());
134 for (unsigned short i = 0; i < 2; i++) m_DQMnSamplesHisto2->GetYaxis()->SetBinLabel(i + 1, Ysamples[i].Data());
135
136 //preparing X and Y axis of the DQMtrgQuality histograms
137 for (unsigned short i = 0; i < 4; i++) m_DQMtrgQuality->GetXaxis()->SetBinLabel(i + 1, Xquality[i].Data());
138 for (unsigned short i = 0; i < 2; i++) m_DQMtrgQuality->GetYaxis()->SetBinLabel(i + 1, Ysamples[i].Data());
139
140 m_DQMErrorEventsHisto->GetXaxis()->SetBinLabel(1, "No Errors");
141 m_DQMErrorEventsHisto->GetXaxis()->SetBinLabel(2, "Any Error");
142 m_DQMErrorEventsHisto->GetXaxis()->SetBinLabel(3, "SEU Event");
143 m_DQMErrorEventsHisto->GetXaxis()->SetBinLabel(4, "Empty Event (Recovery)");
144
145 m_DQMSeuRecoveryFADCsEventHisto->GetXaxis()->SetTitle("number of affected FADCs");
146
147 oldDir->cd();
148}
149
151{
152 m_eventMetaData.isRequired();
155 m_objTrgSummary.isOptional();
156
157 // Register histograms (calls back defineHisto)
158 REG_HISTOGRAM
159}
160
161
163{
164
165 StoreObjPtr<EventMetaData> evtMetaData;
166 m_expNumber = evtMetaData->getExperiment();
167 m_runNumber = evtMetaData->getRun();
168 m_errorFraction = 0;
169
170 TString runID = TString::Format(" ~ Exp %d Run %d", m_expNumber, m_runNumber);
171
172 if (m_DQMUnpackerHisto != nullptr) {
173 TString tmp = m_DQMUnpackerHisto->GetTitle();
174 Int_t pos = tmp.Last('~');
175 if (pos == -1) pos = tmp.Length() + 2;
176 TString title = tmp(0, pos - 2);
177 m_DQMUnpackerHisto->SetTitle(title + runID);
178 m_DQMUnpackerHisto->Reset();
179 }
180
181 if (m_DQMErrorEventsHisto != nullptr) {
182 TString tmp = m_DQMErrorEventsHisto->GetTitle();
183 Int_t pos = tmp.Last('~');
184 if (pos == -1) pos = tmp.Length() + 2;
185 TString title = tmp(0, pos - 2);
186 m_DQMErrorEventsHisto->SetTitle(title + runID);
187 m_DQMErrorEventsHisto->Reset();
188 }
189
190 if (m_DQMSeuRecoveryFADCsEventHisto != nullptr) {
191 TString tmp = m_DQMSeuRecoveryFADCsEventHisto->GetTitle();
192 Int_t pos = tmp.Last('~');
193 if (pos == -1) pos = tmp.Length() + 2;
194 TString title = tmp(0, pos - 2);
195 m_DQMSeuRecoveryFADCsEventHisto->SetTitle(title + runID);
197 }
198
199 if (m_DQMnSamplesHisto != nullptr) {
200 TString tmp = m_DQMnSamplesHisto->GetTitle();
201 Int_t pos = tmp.Last('~');
202 if (pos == -1) pos = tmp.Length() + 2;
203 TString title = tmp(0, pos - 2);
204 m_DQMnSamplesHisto->SetTitle(title + runID);
205 m_DQMnSamplesHisto->Reset();
206 }
207
208 if (m_DQMnSamplesHisto2 != nullptr) {
209 TString tmp = m_DQMnSamplesHisto2->GetTitle();
210 Int_t pos = tmp.Last('~');
211 if (pos == -1) pos = tmp.Length() + 2;
212 TString title = tmp(0, pos - 2);
213 m_DQMnSamplesHisto2->SetTitle(title + runID);
214 m_DQMnSamplesHisto2->Reset();
215 }
216
217 if (m_DQMtrgQuality != nullptr) {
218 TString tmp = m_DQMtrgQuality->GetTitle();
219 Int_t pos = tmp.Last('~');
220 if (pos == -1) pos = tmp.Length() + 2;
221 TString title = tmp(0, pos - 2);
222 m_DQMtrgQuality->SetTitle(title + runID);
223 m_DQMtrgQuality->Reset();
224 }
225
226 m_shutUpNoData = false;
227
228 if (m_mapping.hasChanged()) { m_map = std::make_unique<SVDOnlineToOfflineMap>(m_mapping->getFileName()); }
229
230 m_changeFADCaxis = false;
231
232 //getting fadc numbers from the mapping
233 m_FADCs = &(m_map->FADCnumbers);
234
235 //copy FADC numbers to vector and sort them
236 m_vec_fadc.insert(m_vec_fadc.end(), m_FADCs->begin(), m_FADCs->end());
237 std::sort(m_vec_fadc.begin(), m_vec_fadc.end());
238
239 unsigned short ifadc = 0;
240 for (const auto& fadc : m_vec_fadc) {
241 m_fadc_map.insert(make_pair(fadc, ++ifadc));
242 m_DQMUnpackerHisto->GetYaxis()->SetBinLabel(ifadc, to_string(fadc).c_str());
243 }
244
245 m_nEvents = 0;
246 m_nBadEvents = 0;
247}
248
249
251{
252 if (!m_svdDAQDiagnostics.isValid()) {
253 if (!m_shutUpNoData)
254 B2WARNING("There are no SVDDAQDiagnostic objects saved by the Unpacker! SVD Data Format Monitoring disabled!");
255 m_shutUpNoData = true;
256 return;
257 }
258
259 if (!m_svdEventInfo.isValid()) {
260 if (!m_shutUpNoData)
261 B2WARNING("There is no SVDEventInfo object saved by the Unpacker! SVD Data Format Monitoring disabled!");
262 m_shutUpNoData = true;
263 return;
264 }
265
266 m_badEvent = 0;
267 m_seuEvent = 0;
268 m_seuRecoEvent = 0;
269 m_seuFADCs.clear();
270
271 m_nEvents++;
272
273 // filling nSamplesHisto
274 int daqMode = m_svdEventInfo->getModeByte().getDAQMode();
275 int nSamples = m_svdEventInfo->getNSamples();
276
277 m_DQMnSamplesHisto->Fill(daqMode, nSamples / 3);
278 if (daqMode < 3) m_DQMnSamplesHisto2->Fill(daqMode, nSamples / 3);
279
280
281 //filling TRGqualityHisto
282 if (m_objTrgSummary.isValid()) {
283 int trgQuality = m_objTrgSummary->getTimQuality();
284 m_DQMtrgQuality->Fill(trgQuality, nSamples / 3);
285 } else m_DQMtrgQuality->Fill(4, nSamples / 3);
286
287
288 //filling m_DQMUnpackerHisto
289 unsigned int nDiagnostics = m_svdDAQDiagnostics.getEntries();
290
291 unsigned short bin_no = 0;
292 gStyle->SetOptStat(0);
293
294 for (unsigned short i = 0; i < nDiagnostics; i++) {
295
296 m_ftbFlags = m_svdDAQDiagnostics[i]->getFTBFlags();
297 m_ftbError = m_svdDAQDiagnostics[i]->getFTBError();
298 m_apvError = m_svdDAQDiagnostics[i]->getAPVError();
299 m_apvMatch = m_svdDAQDiagnostics[i]->getAPVMatch();
300 m_fadcMatch = m_svdDAQDiagnostics[i]->getFADCMatch();
301 m_upsetAPV = m_svdDAQDiagnostics[i]->getUpsetAPV();
302 m_badMapping = m_svdDAQDiagnostics[i]->getBadMapping();
303 m_badHeader = m_svdDAQDiagnostics[i]->getBadHeader();
304 m_badTrailer = m_svdDAQDiagnostics[i]->getBadTrailer();
305 m_missedHeader = m_svdDAQDiagnostics[i]->getMissedHeader();
306 m_missedTrailer = m_svdDAQDiagnostics[i]->getMissedTrailer();
307 m_seuRecoData = m_svdDAQDiagnostics[i]->getSEURecoData();
308
309 m_fadcNo = m_svdDAQDiagnostics[i]->getFADCNumber();
310 m_apvNo = m_svdDAQDiagnostics[i]->getAPVNumber();
311
312 // insert FADCnumber into the map (if not already there) and assign the next bin to it.
313 if (m_changeFADCaxis) {
314 if (m_fadc_map.find(m_fadcNo) == m_fadc_map.end()) m_fadc_map.insert(make_pair(m_fadcNo, ++bin_no));
315 }
316
317 if (m_ftbFlags != 0 or m_ftbError != 240 or m_apvError != 0 or !m_apvMatch or !m_fadcMatch or m_upsetAPV or m_badMapping
318 or m_badHeader
320
321 m_badEvent = 1;
322
323 auto ybin = m_fadc_map.find(m_fadcNo);
324
325 if (m_badMapping) {
326 if (!m_changeFADCaxis) {
327 m_changeFADCaxis = true;
328 m_fadc_map.clear();
329 break;
330 } else {
331 m_DQMUnpackerHisto->Fill(20, ybin->second);
332 }
333 }
334
335 if (m_apvError & 8 or m_apvError & 4 or m_upsetAPV) {
336 m_seuEvent = 1;
337
338 //let's retrieve the sensor info for this SEU case
339 SVDOnlineToOfflineMap::SensorInfo theVxdInfo = m_map->getSensorInfo(m_fadcNo, m_apvNo);
340 VxdID::baseType theVxdID = theVxdInfo.m_sensorID;
341 bool side = theVxdInfo.m_uSide;
342
343 m_SEUonSensors->fill(theVxdID, side, 1);
344 }
345
346 if (m_badHeader) m_DQMUnpackerHisto->Fill(17, ybin->second);
347 if (m_missedHeader) m_DQMUnpackerHisto->Fill(18, ybin->second);
348 if (m_badTrailer or m_missedTrailer) m_DQMUnpackerHisto->Fill(19, ybin->second);
349
350 if (m_ftbFlags != 0) {
351 if (m_ftbFlags & 16) m_DQMUnpackerHisto->Fill(5, ybin->second);
352 if (m_ftbFlags & 8) m_DQMUnpackerHisto->Fill(4, ybin->second);
353 if (m_ftbFlags & 4) m_DQMUnpackerHisto->Fill(3, ybin->second);
354 if (m_ftbFlags & 2) m_DQMUnpackerHisto->Fill(2, ybin->second);
355 if (m_ftbFlags & 1) m_DQMUnpackerHisto->Fill(1, ybin->second);
356 }
357 if (m_ftbError != 240) {
358 switch (m_ftbError - 240) {
359 case 3:
360 m_DQMUnpackerHisto->Fill(6, ybin->second); //badFADC
361 break;
362 case 5:
363 m_DQMUnpackerHisto->Fill(7, ybin->second); //badTTD
364 break;
365 case 6:
366 m_DQMUnpackerHisto->Fill(8, ybin->second); //badFTB
367 break;
368 case 7:
369 m_DQMUnpackerHisto->Fill(9, ybin->second);//badALL;
370 break;
371 }
372 }
373
374 if (m_apvError != 0) {
375 if (m_apvError & 8) m_DQMUnpackerHisto->Fill(10, ybin->second);
376 if (m_apvError & 4) m_DQMUnpackerHisto->Fill(11, ybin->second);
377 if (m_apvError & 2) m_DQMUnpackerHisto->Fill(12, ybin->second);
378 if (m_apvError & 1) m_DQMUnpackerHisto->Fill(13, ybin->second);
379 }
380
381 if (!m_apvMatch) m_DQMUnpackerHisto->Fill(14, ybin->second);
382 if (!m_fadcMatch) m_DQMUnpackerHisto->Fill(15, ybin->second);
383 if (m_upsetAPV) m_DQMUnpackerHisto->Fill(16, ybin->second);
384 if (m_seuRecoData) {
385
386 m_DQMUnpackerHisto->Fill(21, ybin->second);
387 m_seuRecoEvent = 1;
388 m_seuFADCs.insert(ybin->first);
389
390 }
391
392 }
393 } //end Diagnostics loop
394
395
396 if (m_changeFADCaxis) {
397 for (auto& iFADC : m_fadc_map) m_DQMUnpackerHisto->GetYaxis()->SetBinLabel(iFADC.second, to_string(iFADC.first).c_str());
398 }
400 m_errorFraction = 100 * float(m_nBadEvents) / float(m_nEvents);
401
402 if (m_DQMErrorEventsHisto != nullptr) {
403 TString histoErrorTitle = TString::Format("SVD Events with errors, Exp %d Run %d", m_expNumber, m_runNumber);
404 m_DQMErrorEventsHisto->SetTitle(histoErrorTitle.Data());
405 if (!m_badEvent) m_DQMErrorEventsHisto->Fill(0);
406 else m_DQMErrorEventsHisto->Fill(1);
407 if (m_seuEvent) m_DQMErrorEventsHisto->Fill(2);
409 }
410
411 if (m_DQMSeuRecoveryFADCsEventHisto != nullptr) {
412 TString histoSEURecoFADCsTitle = TString::Format("Number of FADCs with Empty Data (SEURecovery) per Event, Exp %d Run %d",
414 m_DQMSeuRecoveryFADCsEventHisto->SetTitle(histoSEURecoFADCsTitle.Data());
415 if (m_seuFADCs.size() > 0) {
416 m_DQMSeuRecoveryFADCsEventHisto->SetMaximum(-1111);
418 }
419 }
420} // end event function
421
422
424{
425 // Summary report on SVD DQM monitor
426 if (m_nBadEvents) {
427 B2WARNING("=================== SVD DQM Data Format Statistics: =============");
428 B2WARNING(" We found " << m_nBadEvents << "/" << m_nEvents << " corrupted events, which is " << m_errorFraction <<
429 "%");
430 B2WARNING("=================================================================");
431 }
432
433}
HistoModule()
Constructor.
Definition HistoModule.h:32
void setDescription(const std::string &description)
Sets the description of the module.
Definition Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition Module.h:80
class to summarize SVD quantities per sensor and side
TH1F * m_DQMSeuRecoveryFADCsEventHisto
TH1F histogram showing the number of FADC with SEU recoveries per event.
unsigned int m_nBadEvents
counter of events with any kind of error
void initialize() override final
Module function initialize.
TH2F * m_DQMnSamplesHisto2
TH2F histogram showing number of samples in data VS daqMode (2bins only)
unsigned short m_apvNo
apv number
bool m_seuEvent
indicates if the particular event is SEU case
unsigned int m_nEvents
event counter
bool m_seuRecoData
special SEU recovery data
StoreObjPtr< SVDEventInfo > m_svdEventInfo
SVDEventInfo StoreObjectPointer.
bool m_missedHeader
missed Header error
bool m_shutUpNoData
shut up if no data comes
TH2F * m_DQMUnpackerHisto
TH2F histogram with Unpacking errors.
std::string m_SVDDAQDiagnosticsName
SVD diagnostics module name.
StoreArray< SVDDAQDiagnostic > m_svdDAQDiagnostics
SVDDAQDiagnostic StoreArray.
std::vector< unsigned short > m_vec_fadc
vector of FADC boards
std::unordered_map< unsigned short, unsigned short > m_fadc_map
FADC board number map.
void defineHisto() override final
Histogram definitions such as TH1(), TH2(), TNtuple(), TTree()....
DBObjPtr< PayloadFile > m_mapping
channel map payload
float m_errorFraction
fraction of events with any kind of error
TH2F * m_DQMnSamplesHisto
TH2F histogram showing number of samples in data VS daqMode.
bool m_seuRecoEvent
indicates if the particular event is SEU recovery case
StoreObjPtr< EventMetaData > m_eventMetaData
EvtMetaData StoreObjectPointer.
static std::string m_xmlFileName
xml filename
void event() override final
Module function event.
StoreObjPtr< TRGSummary > m_objTrgSummary
Trigger Summary data object.
std::string m_histogramDirectoryName
Name of the histogram directory in ROOT file.
bool m_missedTrailer
missed Trailer error
std::unordered_set< unsigned char > * m_FADCs
FADC boards number.
TH2F * m_DQMtrgQuality
TH2F histogram showing number of samples in data VS Trigger Quality.
void endRun() override final
Module function endRun.
uint16_t m_apvError
APV error container.
std::string m_SVDEventInfoName
SVDEventInfo name.
unsigned short m_fadcNo
fadc number
std::unordered_set< unsigned char > m_seuFADCs
FADC numbers affected by SEU.
void beginRun() override final
Module function beginRun.
bool m_badEvent
indicates if the particular event has any SVD error
SVDSummaryPlots * m_SEUonSensors
histogram showing SEU Reco events for given sensor
std::unique_ptr< SVDOnlineToOfflineMap > m_map
mapping implementation
TH1F * m_DQMErrorEventsHisto
TH1F histogram showing the events affected by errors.
uint16_t m_ftbError
FTB error container.
uint16_t m_ftbFlags
FTB flags container.
bool m_changeFADCaxis
change FADC (y) axis
Type-safe access to single objects in the data store.
Definition StoreObjPtr.h:96
unsigned short baseType
The base integer type for VxdID.
Definition VxdID.h:36
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
Abstract base class for different kinds of events.
STL namespace.
Struct to hold data about a sensor.
bool m_uSide
True if u-side of the sensor.