Belle II Software development
DQMHistAnalysisECL.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//THIS MODULE
10#include <dqm/analysis/modules/DQMHistAnalysisECL.h>
11
12//ROOT
13#include <TROOT.h>
14#include <TStyle.h>
15#include <TColor.h>
16
17//std
18#include <sstream>
19
20//boost
21#include "boost/format.hpp"
22
23using namespace Belle2;
24
25REG_MODULE(DQMHistAnalysisECL);
26
29{
30 B2DEBUG(20, "DQMHistAnalysisECL: Constructor done.");
31
32 m_WaveformOption = {"psd", "logic", "rand", "dphy", "other"};
34 "Provide a large number of ECL DQM analysis histograms:\n"
35 " 1. Normalize some low-level DQM histograms by the event count.\n"
36 " 2. Display time offsets for each ECL crate.\n"
37 " 3. Display the number of failed fits in each ECL module.");
38 addParam("HitMapThresholds", m_HitMapThresholds, "Thresholds to display hit map, MeV", std::vector<double> {0, 5, 10, 50});
39 addParam("WaveformOption", m_WaveformOption, "Option (all,psd,logic,rand,dphy) to display waveform flow",
41 addParam("CrateTimeOffsetsMax", m_CrateTimeOffsetsMax, "Maximum boundary for crate time offsets", 20.);
42 addParam("LogicTestMax", m_LogicTestMax, " Maximum of fails for logic test", 50);
43 addParam("pvPrefix", m_pvPrefix, "Prefix to use for PVs registered by this module",
44 std::string("ECL:"));
45}
46
47
49
51{
52 gROOT->cd();
53 B2DEBUG(20, "DQMHistAnalysisECL: initialized.");
54
55 //new canvases for existing histograms
56 c_quality_analysis = new TCanvas("ECL/c_quality_analysis");
57 c_quality_other_analysis = new TCanvas("ECL/c_quality_other_analysis");
58 c_bad_quality_analysis = new TCanvas("ECL/c_bad_quality_analysis");
59 c_trigtag1_analysis = new TCanvas("ECL/c_trigtag1_analysis");
60 c_trigtag2_analysis = new TCanvas("ECL/c_trigtag2_analysis");
61 c_adc_hits_analysis = new TCanvas("ECL/c_adc_hits_analysis");
62 c_ampfail_quality_analysis = new TCanvas("ECL/c_ampfail_quality_analysis");
63 c_timefail_quality_analysis = new TCanvas("ECL/c_timefail_quality_analysis");
64 c_quality_fit_data_analysis = new TCanvas("ECL/c_quality_fit_data_analysis");
65
66 for (const auto& id : m_HitMapThresholds) {
67 std::string canvas_name = str(boost::format("ECL/c_cid_Thr%1%MeV_analysis") % id);
68 TCanvas* canvas = new TCanvas(canvas_name.c_str());
69 c_cid_analysis.push_back(canvas);
70 }
71
72 for (const auto& id : m_WaveformOption) {
73 if (id != "other") {
74 std::string canvas_name = str(boost::format("ECL/c_wf_cid_%1%_analysis") % id);
75 TCanvas* canvas = new TCanvas(canvas_name.c_str());
76 c_wf_analysis.push_back(canvas);
77 }
78 }
79
80 //Boundaries for 'trigtag2_trigid' histogram
81 m_lower_boundary_trigtag2 = new TLine(1, 0, 53, 0);
82 m_lower_boundary_trigtag2->SetLineWidth(3);
83 m_lower_boundary_trigtag2->SetLineColor(kBlue);
84
85 m_upper_boundary_trigtag2 = new TLine(1, 1, 53, 1);
86 m_upper_boundary_trigtag2->SetLineWidth(3);
87 m_upper_boundary_trigtag2->SetLineColor(kBlue);
88 //Boundaries for 'crate_time_offset' plot
89 m_lower_boundary_time_offsets = new TLine(0, -20, 52, -20);
90 m_lower_boundary_time_offsets->SetLineWidth(3);
91 m_lower_boundary_time_offsets->SetLineColor(kBlue);
92
93 m_upper_boundary_time_offsets = new TLine(0, 20, 52, 20);
94 m_upper_boundary_time_offsets->SetLineWidth(3);
95 m_upper_boundary_time_offsets->SetLineColor(kBlue);
96
97 //Summary crate_time_offsets plot
98 c_crate_time_offsets = new TCanvas("ECL/c_crate_time_offsets", "", 840, 840);
99 h_crate_time_offsets = new TGraphErrors();
100 h_crate_time_offsets->SetName("t_off");
101 h_crate_time_offsets->SetTitle("Crate time offset (E > 1 GeV); Crate ID (same as ECLCollector ID); Time offset [ns]");
102 h_crate_time_offsets->SetMarkerColor(kBlue);
103 h_crate_time_offsets->SetMarkerStyle(20);
104
105 //New DQM summary for logic test in CR shifter panel
106 c_logic_summary = new TCanvas("ECL/c_logic_summary");
107 h_logic_summary = new TH2F("logic_summary", "FPGA <-> C++ fitter inconsistencies count", 52, 1, 53, 12, 1, 13);
108 h_logic_summary->SetTitle("FPGA <-> C++ fitter inconsistencies count; ECLCollector ID (same as Crate ID); Shaper ID inside the crate");
109 h_logic_summary->SetCanExtend(TH1::kAllAxes);
110 h_logic_summary->SetStats(0);
111 for (unsigned short i = 0; i < 52; i++) h_logic_summary->GetXaxis()->SetBinLabel(i + 1, std::to_string(i + 1).c_str());
112 for (unsigned short i = 0; i < 12; i++) h_logic_summary->GetYaxis()->SetBinLabel(i + 1, std::to_string(i + 1).c_str());
113 h_logic_summary->LabelsOption("v");
114 h_logic_summary->SetTickLength(0, "xy");
115
116
117 //EPICS PVs for 'crate_time_offset' plot
118 for (unsigned short i = 0; i < 52; i++) {
119 auto pv_name = (boost::format("time_offset:crate%02d") % (i + 1)).str();
120 registerEpicsPV(m_pvPrefix + pv_name, pv_name);
121 }
122 for (auto wf_option : m_WaveformOption) {
123 auto pv_name = (boost::format("wf_frac:%s:min") % wf_option).str();
124 registerEpicsPV(m_pvPrefix + pv_name, pv_name);
125 }
126
128}
129
131{
132 B2DEBUG(20, "DQMHistAnalysisECL: beginRun called.");
133}
134
135void DQMHistAnalysisECLModule::normalize(TCanvas* c, const std::string& h_name, const Double_t& weight)
136{
137 c->Clear();
138 c->cd();
139 TH1* h = findHist(h_name);
140 if (h != NULL) {
141 for (unsigned short i = 0; i < h->GetNbinsX(); i++) {
142 Double_t entries = h->GetBinContent(i + 1);
143 Double_t error = h->GetBinError(i + 1);
144 if (weight) {
145 h->SetBinContent(i + 1, entries / weight);
146 h->SetBinError(i + 1, error / weight);
147 }
148 }
149 h->Draw("HIST");
150 }
151 c->Draw();
152 c->Modified();
153 c->Update();
154}
155
157{
158 B2DEBUG(20, "DQMHistAnalysisECL: event called");
159
160 //gStyle requirements
161 gStyle->SetPalette(1);
162
163 //1D histos
164 //quality
165 c_quality_analysis->Clear();
166 c_quality_analysis->cd();
167 c_quality_analysis->SetLogy();
168 TH1* h_quality = findHist("ECL/quality");
169 if (h_quality != NULL) {
170 h_quality->SetFillColor(kPink - 4);
171 h_quality->SetDrawOption("hist");
172 h_quality->SetMinimum(0.1);
173 h_quality->Draw("hist");
174 }
175 c_quality_analysis->Draw();
176 c_quality_analysis->Modified();
177 c_quality_analysis->Update();
178
179 //quality_other
182 c_quality_other_analysis->SetLogy();
183 TH1* h_quality_other = findHist("ECL/quality_other");
184 if (h_quality_other != NULL) {
185 h_quality_other->SetMinimum(0.1);
186 h_quality_other->SetFillColor(kPink - 4);
187 h_quality_other->Draw("hist");
188 }
190 c_quality_other_analysis->Modified();
191 c_quality_other_analysis->Update();
192
193 //bad_quality ,cid_Thr%1%MeV, wf_cid_%1%, wf_sh_%1%, wf_cr_%1%
194 TH1* h_evtot = findHist("ECL/event");
195 if (h_evtot != NULL) {
196 Double_t events = h_evtot->GetBinContent(1);
197 normalize(c_bad_quality_analysis, "ECL/bad_quality", events);
198 for (std::size_t i = 0; i < m_HitMapThresholds.size(); ++i)
200 str(boost::format("ECL/cid_Thr%1%MeV") % m_HitMapThresholds[i]), events);
201 }
202 for (std::size_t i = 0; i < m_WaveformOption.size(); ++i) {
203 auto val = m_WaveformOption[i];
204 if (val != "psd" && val != "other") {
205 TH1* h_evtot_norm = findHist(str(boost::format("ECL/event_%1%") % val));
206 if (h_evtot_norm != NULL) {
207 Double_t events = h_evtot_norm->GetBinContent(1);
209 str(boost::format("ECL/wf_cid_%1%") % val), events);
210 }
211 } else if (val == "psd") {
212 c_wf_analysis[i]->Clear();
213 c_wf_analysis[i]->cd();
214 TH1* h_psd = findHist(str(boost::format("ECL/wf_cid_%1%") % val));
215 TH1* h_psd_norm = findHist(str(boost::format("ECL/%1%_cid") % val));
216 if (h_psd != NULL && h_psd_norm != NULL) {
217 h_psd->Divide(h_psd, h_psd_norm);
218 h_psd->Draw("HIST");
219 }
220 c_wf_analysis[i]->Draw();
221 c_wf_analysis[i]->Modified();
222 c_wf_analysis[i]->Update();
223 }
224 } //m_WaveformOption
225
226 //trigtag1
227 c_trigtag1_analysis->Clear();
229 c_trigtag1_analysis->Pad()->SetFrameFillColor(10);
230 c_trigtag1_analysis->Pad()->SetFillColor(c_ColorDefault);
231 c_trigtag1_analysis->SetLogy();
232 TH1* h_trigtag1 = findHist("ECL/trigtag1");
233 if (h_trigtag1 != NULL) {
234 h_trigtag1->SetMinimum(0.1);
235 h_trigtag1->Draw("hist");
236 if (h_trigtag1->GetBinContent(2)) c_trigtag1_analysis->Pad()->SetFillColor(c_ColorError);
237 }
238 c_trigtag1_analysis->Draw();
239 c_trigtag1_analysis->Modified();
240 c_trigtag1_analysis->Update();
241
242 //adc_hits
243 c_adc_hits_analysis->Clear();
245 c_adc_hits_analysis->SetLogy();
246 TH1* h_adc_hits = findHist("ECL/adc_hits");
247 if (h_adc_hits != NULL) {
248 h_adc_hits->SetMinimum(0.1);
249 h_adc_hits->Draw("hist");
250 }
251 c_adc_hits_analysis->Draw();
252 c_adc_hits_analysis->Modified();
253 c_adc_hits_analysis->Update();
254
255 //ampfail_quality
258 c_ampfail_quality_analysis->Pad()->SetFrameFillColor(10);
259 c_ampfail_quality_analysis->Pad()->SetFillColor(c_ColorDefault);
261 TH1* h_ampfail_quality = findHist("ECL/ampfail_quality");
262 if (h_ampfail_quality != NULL) {
263 h_ampfail_quality->SetMinimum(0.1);
264 h_ampfail_quality->Draw("hist");
265 for (unsigned short i = 1; i < 5; i++) {
266 if (h_ampfail_quality->GetBinContent(i + 1)) {
267 c_ampfail_quality_analysis->Pad()->SetFillColor(c_ColorError);
268 break;
269 }
270 }
271 }
273 c_ampfail_quality_analysis->Modified();
275
276 //timefail_quality
279 c_timefail_quality_analysis->Pad()->SetFrameFillColor(10);
280 c_timefail_quality_analysis->Pad()->SetFillColor(c_ColorDefault);
282 TH1* h_timefail_quality = findHist("ECL/timefail_quality");
283 if (h_timefail_quality != NULL) {
284 h_timefail_quality->SetMinimum(0.1);
285 h_timefail_quality->Draw("hist");
286 for (unsigned short i = 1; i < 5; i++) {
287 if (h_timefail_quality->GetBinContent(i + 1)) {
288 c_timefail_quality_analysis->Pad()->SetFillColor(c_ColorError);
289 break;
290 }
291 }
292 }
294 c_timefail_quality_analysis->Modified();
296
297 //2D histos
298 //trigtag2_trigid
299 c_trigtag2_analysis->Clear();
301 c_trigtag2_analysis->Pad()->SetFrameFillColor(10);
302 c_trigtag2_analysis->Pad()->SetFillColor(c_ColorDefault);
303 TH1* h_trigtag2_trigid = findHist("ECL/trigtag2_trigid");
304 if (h_trigtag2_trigid != NULL) {
305 h_trigtag2_trigid->Draw("colz");
306 for (unsigned short i = 0; i < 52; i++) {
307 if (h_trigtag2_trigid->GetBinContent(h_trigtag2_trigid->GetBin(i + 1, 3))) {
308 c_trigtag2_analysis->Pad()->SetFillColor(c_ColorError);
309 break;
310 }
311 }
312 }
315
316 c_trigtag2_analysis->Draw();
317 c_trigtag2_analysis->Modified();
318 c_trigtag2_analysis->Update();
319
320 //quality_fit_data
323 c_quality_fit_data_analysis->Pad()->SetFrameFillColor(10);
324 c_quality_fit_data_analysis->Pad()->SetFillColor(c_ColorDefault);
325 TH1* h_quality_fit_data = findHist("ECL/quality_fit_data");
326 if (h_quality_fit_data != NULL) {
327 h_quality_fit_data->Draw("hist");
328 for (unsigned short i = 0; i < 4; i++) {
329 for (unsigned short j = 0; j < 4; j++) {
330 if (h_quality_fit_data->GetBinContent(h_quality_fit_data->GetBin(i + 1, j + 1)) > 0) {
331 c_quality_fit_data_analysis->Pad()->SetFillColor(c_ColorError);
332 break;
333 }
334 }
335 }
336 }
338 c_quality_fit_data_analysis->Modified();
340
341 //_time_crate_%1%_Thr1GeV
342 bool crates_bad_timing = false;
343
344 m_low.clear();
345 h_crate_time_offsets->Set(0);
346
347 for (unsigned short i = 0; i < 52; i++) {
348 m_crate_time_offsets[i] = std::numeric_limits<double>::quiet_NaN();
349
350 std::string h_title = "ECL/time_crate_" + std::to_string(i + 1) + "_Thr1GeV";
352 if (h_time_crate_Thr1GeV != NULL) {
354 h_crate_time_offsets->SetPoint(i, i + 0.5, h_time_crate_Thr1GeV->GetMean());
355 h_crate_time_offsets->SetPointError(i, 0.1, h_time_crate_Thr1GeV->GetMeanError());
356
357 if (h_time_crate_Thr1GeV->Integral() > 100) {
358 double yval = (h_time_crate_Thr1GeV->GetMean() > 0) ?
359 h_time_crate_Thr1GeV->GetMean() - 2 * h_time_crate_Thr1GeV->GetMeanError() :
360 h_time_crate_Thr1GeV->GetMean() + 2 * h_time_crate_Thr1GeV->GetMeanError();
361 if (fabs(yval) > m_CrateTimeOffsetsMax) crates_bad_timing = true;
362 } else {
363 m_low.push_back(i + 1);
364 }
365 }
366 auto pv_name = (boost::format("time_offset:crate%02d") % (i + 1)).str();
367 setEpicsPV(pv_name, m_crate_time_offsets[i]);
368 }
369
370 c_crate_time_offsets->Clear();
371 c_crate_time_offsets->SetGrid();
373
374 c_crate_time_offsets->Pad()->SetFrameFillColor(10);
375 c_crate_time_offsets->Pad()->SetFillColor(c_ColorDefault);
376
377 h_crate_time_offsets->SetMinimum(-50);
378 h_crate_time_offsets->SetMaximum(50);
379 h_crate_time_offsets->GetXaxis()->Set(52, 0, 52);
380 for (unsigned short i = 0; i < 52; i++) h_crate_time_offsets->GetXaxis()->SetBinLabel(i + 1, std::to_string(i + 1).c_str());
381 h_crate_time_offsets->GetXaxis()->LabelsOption("v");
382
383 h_crate_time_offsets->GetHistogram()->Draw();
384 h_crate_time_offsets->Draw("P");
385
386 if (!m_low.empty()) {
387 auto tg = new TLatex(5, 40, "Low statistics");
388 tg->SetTextSize(.06);
389 tg->SetTextAlign(12);
390 tg->Draw();
391 c_crate_time_offsets->Pad()->SetFillColor(c_ColorTooFew);
392 if (m_low.size() < 52) {
393 std::ostringstream sstream;
394 std::copy(m_low.begin(), m_low.end() - 1, std::ostream_iterator<short>(sstream, ","));
395 sstream << m_low.back();
396 std::string str = "Crates: " + sstream.str();
397 auto tg1 = new TLatex(5, 30, str.c_str());
398 tg1->SetTextSize(.03);
399 tg1->SetTextAlign(12);
400 tg1->Draw();
401 } else {
402 auto tg1 = new TLatex(5, 30, "All crates");
403 tg1->SetTextSize(.06);
404 tg1->SetTextAlign(12);
405 tg1->Draw();
406 }
407 }
408
411
412 if (crates_bad_timing) c_crate_time_offsets->Pad()->SetFillColor(c_ColorError);
413
414 c_crate_time_offsets->Draw();
415 c_crate_time_offsets->Modified();
416 c_crate_time_offsets->Update();
417
418 //DQM summary logic
419 h_logic_summary->Reset();
420
421 TH1* h_fail_crateid = findHist("ECL/fail_crateid");
422 TH1* h_fail_shaperid = findHist("ECL/fail_shaperid");
423 if (h_fail_crateid != NULL && h_fail_shaperid != NULL) {
424 for (unsigned short i = 0; i < 52; i++) {
425 if (h_fail_crateid->GetBinContent(i + 1)) {
426 for (unsigned short j = i * 12; j < i * 12 + 12; j++) {
427 if (h_fail_shaperid->GetBinContent(j + 1)) {
428 unsigned short shaper = (j + 1) - 12 * i;
429 h_logic_summary->SetBinContent(h_logic_summary->FindBin(i + 1, shaper), h_fail_shaperid->GetBinContent(j + 1));
430 }
431 }
432 }
433 }
434 c_logic_summary->Clear();
435 c_logic_summary->SetGrid();
436 c_logic_summary->cd();
437
438 c_logic_summary->Pad()->SetFrameFillColor(10);
439 c_logic_summary->Pad()->SetFillColor(c_ColorGood);
440
441 if (h_logic_summary->GetMaximum() > 0
442 && h_logic_summary->GetMaximum() < m_LogicTestMax) c_logic_summary->Pad()->SetFillColor(c_ColorWarning);
443 if (h_logic_summary->GetMaximum() >= m_LogicTestMax) c_logic_summary->Pad()->SetFillColor(c_ColorError);
444 h_logic_summary->Draw("textcol");
445 c_logic_summary->Draw();
446 c_logic_summary->Modified();
447 c_logic_summary->Update();
448 }
449
450 //Set EPICS PVs
451 if (h_evtot == NULL) return;
452
453 Double_t events = h_evtot->GetBinContent(1);
454 for (auto wf_option : m_WaveformOption) {
455 m_wf_fraction[wf_option] = std::numeric_limits<double>::quiet_NaN();
456 // Get minimal value for each type of saved waveforms
457 if (events > 100000) {
458 TH1* hist = findHist(str(boost::format("ECL/wf_cid_%1%") % wf_option));
459 m_wf_fraction[wf_option] = hist->GetBinContent(hist->GetMinimumBin());
460 }
461 auto pv_name = (boost::format("wf_frac:%s:min") % wf_option).str();
462 setEpicsPV(pv_name, m_wf_fraction[wf_option]);
463 }
464}
465
467{
468 B2DEBUG(20, "DQMHistAnalysisECL: endRun called");
469 for (unsigned short i = 0; i < 52; i++) {
470 auto var_name = (boost::format("time_offset_crate%02d") % (i + 1)).str();
472 }
473 for (auto wf_option : m_WaveformOption) {
474 auto var_name = (boost::format("wf_frac_%s_min") % wf_option).str();
475 m_monObj->setVariable(var_name, m_wf_fraction[wf_option]);
476 }
477}
478
479
481{
482 B2DEBUG(20, "terminate called");
483 delete c_quality_analysis;
486 delete c_trigtag1_analysis;
487 delete c_trigtag2_analysis;
488 delete c_adc_hits_analysis;
499 delete c_logic_summary;
500 delete h_logic_summary;
501}
std::vector< double > m_HitMapThresholds
Parameters for hit map histograms.
void normalize(TCanvas *, const std::string &, const Double_t &)
Normalize histograms.
void initialize() override final
Initialize the module.
TCanvas * c_bad_quality_analysis
TCanvas for bad_quality .
std::vector< TCanvas * > c_wf_analysis
Vector of TCanvases for waveforms .
TLine * m_lower_boundary_trigtag2
TLine to show lower boundary for 'trigtag2_trigid' histogram.
int m_LogicTestMax
Maximum of fails for logic test.
TCanvas * c_crate_time_offsets
TCanvas for time offsets.
TH1 * h_time_crate_Thr1GeV
Histogram showing signal times from ECL crates (Thr.
DQMHistAnalysisECLModule()
< derived from DQMHistAnalysisModule class.
TCanvas * c_quality_fit_data_analysis
TCanvas for quality_fit_data .
TCanvas * c_ampfail_quality_analysis
TCanvas for ampfail_quality .
std::string m_pvPrefix
Prefix to use for PVs registered by this module.
MonitoringObject * m_monObj
MiraBelle monitoring object.
void terminate() override final
Terminate.
double m_crate_time_offsets[52]
Values of crate time offsets.
TLine * m_upper_boundary_time_offsets
TLine to show upper boundary for 'crate_time_offsets' graph.
void event() override final
Event processor.
std::map< std::string, double > m_wf_fraction
Minimum fraction of saved waveforms for each waveform type.
TLine * m_upper_boundary_trigtag2
TLine to show upper boundary for 'trigtag2_trigid' histogram.
std::vector< short > m_low
Vector for crates IDs w/ low statistics.
std::vector< std::string > m_WaveformOption
Options for waveform histograms.
TCanvas * c_quality_analysis
TCanvas for quality .
TH2F * h_logic_summary
Histogram for ECL logic summary.
void endRun() override final
Call when a run ends.
TCanvas * c_adc_hits_analysis
TCanvas for adc_hits .
TCanvas * c_logic_summary
TCanvas for ECL logic summary.
void beginRun() override final
Call when a run begins.
TGraphErrors * h_crate_time_offsets
Graph for time offsets.
TLine * m_lower_boundary_time_offsets
TLine to show lower boundary for 'crate_time_offsets' graph.
TCanvas * c_quality_other_analysis
TCanvas for quality_other .
std::vector< TCanvas * > c_cid_analysis
Vector of TCanvases for hit map .
TCanvas * c_trigtag1_analysis
TCanvas for trigtag1 .
double m_CrateTimeOffsetsMax
Maximum boundary for crate time offsets.
TCanvas * c_trigtag2_analysis
TCanvas for trigtag2 .
TCanvas * c_timefail_quality_analysis
TCanvas for timefail_quality .
The base class for the histogram analysis module.
static MonitoringObject * getMonitoringObject(const std::string &name)
Get MonitoringObject with given name (new object is created if non-existing)
static TH1 * findHist(const std::string &histname, bool onlyIfUpdated=false)
Get histogram from list (no other search).
@ c_ColorWarning
Analysis result: Warning, there may be minor issues.
@ c_ColorError
Analysis result: Severe issue found.
@ c_ColorTooFew
Not enough entries/event to judge.
@ c_ColorGood
Analysis result: Good.
@ c_ColorDefault
default for non-coloring
void setEpicsPV(std::string keyname, double value)
Write value to a EPICS PV.
int registerEpicsPV(std::string pvname, std::string keyname="")
EPICS related Functions.
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setVariable(const std::string &var, float val, float upErr=-1., float dwErr=-1)
set value to float variable (new variable is made if not yet existing)
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
Abstract base class for different kinds of events.