Belle II Software development
DQMHistAnalysisTOP.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 <dqm/analysis/modules/DQMHistAnalysisTOP.h>
10#include <boost/format.hpp>
11#include <boost/algorithm/string.hpp>
12#include <TClass.h>
13#include <TF1.h>
14#include <TROOT.h>
15#include <TStyle.h>
16#include <TProfile.h>
17#include <TString.h>
18#include <map>
19
20using namespace std;
21using namespace Belle2;
22using boost::format;
23
24//-----------------------------------------------------------------
25// Register the Module
26//-----------------------------------------------------------------
27REG_MODULE(DQMHistAnalysisTOP);
28
29//-----------------------------------------------------------------
30// Implementation
31//-----------------------------------------------------------------
32
34{
35 // Set description
36 setDescription("Histogram analysis module for TOP DQM.");
37
38 // Add parameters
39 addParam("asicWindowsBand", m_asicWindowsBand,
40 "lower and upper bin of a band denoting good windows", m_asicWindowsBand);
41 addParam("asicWindowsAlarmLevels", m_asicWindowsAlarmLevels,
42 "alarm levels for the fraction of windows outside the band (yellow, red)", m_asicWindowsAlarmLevels);
43 addParam("eventMonitorAlarmLevels", m_eventMonitorAlarmLevels,
44 "alarm levels for the fraction of desynchronized digits (yellow, red)", m_eventMonitorAlarmLevels);
45 addParam("junkHitsAlarmLevels", m_junkHitsAlarmLevels,
46 "alarm levels for the fraction of junk hits (yellow, red)", m_junkHitsAlarmLevels);
47 addParam("deadChannelsAlarmLevels", m_deadChannelsAlarmLevels,
48 "alarm levels for the fraction of dead + hot channels (yellow, red)", m_deadChannelsAlarmLevels);
49 addParam("backgroundAlarmLevels", m_backgroundAlarmLevels,
50 "alarm levels for background rates [MHz/PMT] (yellow, red)", m_backgroundAlarmLevels);
51 addParam("photonYieldsAlarmLevels", m_photonYieldsAlarmLevels,
52 "alarm levels for the number of photons per track (red, yellow)", m_photonYieldsAlarmLevels);
53 addParam("excludedBoardstacks", m_excludedBoardstacks,
54 "boarstacks to be excluded from alarming. Names are given like '5c', '13d' etc.", m_excludedBoardstacks);
55 addParam("pvPrefix", m_pvPrefix, "Epics PV prefix", std::string("TOP:"));
56 addParam("injectionBGAlarmLevels", m_injectionBGAlarmLevels,
57 "alarm levels for injection background (in % of events)", m_injectionBGAlarmLevels);
58 addParam("timingAlarmLevels", m_timingAlarmLevels,
59 "alarm levels for time distribution (residual fraction w.r.t reference plot)", m_timingAlarmLevels);
60 addParam("eventT0MeanAlarmLevels", m_eventT0MeanAlarmLevels,
61 "alarm levels for mean of event T0 [ns]", m_eventT0MeanAlarmLevels);
62 addParam("eventT0RmsAlarmLevels", m_eventT0RmsAlarmLevels,
63 "alarm levels for r.m.s. of event T0 [ns]", m_eventT0RmsAlarmLevels);
64 addParam("offsetMeanAlarmLevels", m_offsetMeanAlarmLevels,
65 "alarm levels for mean of bunch offset [ns]", m_offsetMeanAlarmLevels);
66 addParam("offsetRmsAlarmLevels", m_offsetRmsAlarmLevels,
67 "alarm levels for r.m.s. of bunch offset [ns]", m_offsetRmsAlarmLevels);
68 addParam("ReferenceFile", m_refFileName, "file name of reference histograms",
69 std::string("/home/group/dqmdaq/references/refHisto.root"));
70
71 B2DEBUG(20, "DQMHistAnalysisTOP: Constructor done.");
72}
73
74
76
77
79{
80
81 // check module parameters
82
83 if (m_asicWindowsBand.size() != 2) B2ERROR("Parameter list 'asicWindowsBand' must contain two numbers");
84 if (m_asicWindowsAlarmLevels.size() != 2) B2ERROR("Parameter list 'asicWindowsAlarmLevels' must contain two numbers");
85 if (m_eventMonitorAlarmLevels.size() != 2) B2ERROR("Parameter list 'eventMonitorAlarmLevels' must contain two numbers");
86 if (m_junkHitsAlarmLevels.size() != 2) B2ERROR("Parameter list 'junkHitsAlarmLevels' must contain two numbers");
87 if (m_deadChannelsAlarmLevels.size() != 2) B2ERROR("Parameter list 'deadChannelsAlarmLevels' must contain two numbers");
88 if (m_backgroundAlarmLevels.size() != 2) B2ERROR("Parameter list 'backgroundAlarmLevels' must contain two numbers");
89 if (m_photonYieldsAlarmLevels.size() != 2) B2ERROR("Parameter list 'photonYieldsAlarmLevels' must contain two numbers");
90 if (m_injectionBGAlarmLevels.size() != 2) B2ERROR("Parameter list 'injectionBGAlarmLevels' must contain two numbers");
91 if (m_timingAlarmLevels.size() != 2) B2ERROR("Parameter list 'timingAlarmLevels' must contain two numbers");
92 if (m_eventT0MeanAlarmLevels.size() != 2) B2ERROR("Parameter list 'eventT0MeanAlarmLevels' must contain two numbers");
93 if (m_eventT0RmsAlarmLevels.size() != 2) B2ERROR("Parameter list 'eventT0RmsAlarmLevels' must contain two numbers");
94 if (m_offsetMeanAlarmLevels.size() != 2) B2ERROR("Parameter list 'offsetMeanAlarmLevels' must contain two numbers");
95 if (m_offsetRmsAlarmLevels.size() != 2) B2ERROR("Parameter list 'offsetRmsAlarmLevels' must contain two numbers");
96
97 // make a map of boardstack names to ID's
98
99 int id = 1;
100 for (int slot = 1; slot <= 16; slot++) {
101 string slotstr = to_string(slot);
102 for (std::string bs : {"a", "b", "c", "d"}) {
103 m_bsmap[slotstr + bs] = id;
104 id++;
105 }
106 }
107
108 // parse excluded boardstacks
109
111
112 // MiraBelle monitoring
113
115
116 // Epics used to pass values to shifter's page (output only)
117
118 registerEpicsPV(m_pvPrefix + "badBoardstacks", "badBoardstacks");
119 registerEpicsPV(m_pvPrefix + "badCarriers", "badCarriers");
120 registerEpicsPV(m_pvPrefix + "badAsics", "badAsics");
121 registerEpicsPV(m_pvPrefix + "badPMTs", "badPMTs");
122 registerEpicsPV(m_pvPrefix + "numExcludedBS", "numExcludedBS");
123 registerEpicsPV(m_pvPrefix + "histoAlarmState", "histoAlarmState"); // to pass overall state to central alarm overview panel
124
125 // Epics used to get limits from configuration file - override module parameters (input only)
126
127 registerEpicsPV(m_pvPrefix + "asicWindowsBand", "asicWindowsBand");
128 registerEpicsPV(m_pvPrefix + "asicWindowsAlarmLevels", "asicWindowsAlarmLevels");
129 registerEpicsPV(m_pvPrefix + "eventMonitorAlarmLevels", "eventMonitorAlarmLevels");
130 registerEpicsPV(m_pvPrefix + "junkHitsAlarmLevels", "junkHitsAlarmLevels");
131 registerEpicsPV(m_pvPrefix + "deadChannelsAlarmLevels", "deadChannelsAlarmLevels");
132 registerEpicsPV(m_pvPrefix + "backgroundAlarmLevels", "backgroundAlarmLevels"); // also output
133 registerEpicsPV(m_pvPrefix + "photonYieldsAlarmLevels", "photonYieldsAlarmLevels");
134 registerEpicsPV(m_pvPrefix + "excludedBoardstacks", "excludedBoardstacks");
135
136 registerEpicsPV(m_pvPrefix + "injectionBGAlarmLevels", "injectionBGAlarmLevels"); // also output
137 registerEpicsPV(m_pvPrefix + "timingAlarmLevels", "timingAlarmLevels");
138 registerEpicsPV(m_pvPrefix + "eventT0MeanAlarmLevels", "eventT0MeanAlarmLevels");
139 registerEpicsPV(m_pvPrefix + "eventT0RmsAlarmLevels", "eventT0RmsAlarmLevels");
140 registerEpicsPV(m_pvPrefix + "offsetMeanAlarmLevels", "offsetMeanAlarmLevels");
141 registerEpicsPV(m_pvPrefix + "offsetRmsAlarmLevels", "offsetRmsAlarmLevels");
142
143 // new canvases, histograms and graphic primitives
144
145 gROOT->cd();
146
147 m_c_photonYields = new TCanvas("TOP/c_photonYields", "c_photonYields");
148 m_c_backgroundRates = new TCanvas("TOP/c_backgroundRates", "c_backgroundRates");
149
150 m_deadFraction = new TH1F("TOP/deadFraction", "Fraction of dead channels in included boardstacks", 16, 0.5, 16.5);
151 m_deadFraction->SetXTitle("slot number");
152 m_deadFraction->SetYTitle("fraction");
153 m_hotFraction = new TH1F("TOP/hotFraction", "Fraction of hot channels in included boardstacks", 16, 0.5, 16.5);
154 m_hotFraction->SetXTitle("slot number");
155 m_hotFraction->SetYTitle("fraction");
156 m_excludedFraction = new TH1F("TOP/excludedFraction", "Fraction of hot and dead channels in excluded bordstacks", 16, 0.5, 16.5);
157 m_excludedFraction->SetXTitle("slot number");
158 m_excludedFraction->SetYTitle("fraction");
159 m_activeFraction = new TH1F("TOP/activeFraction", "Fraction of active channels", 16, 0.5, 16.5);
160 m_activeFraction->SetXTitle("slot number");
161 m_activeFraction->SetYTitle("fraction");
162 m_c_deadAndHot = new TCanvas("TOP/c_deadAndHotChannels", "c_deadAndHotChannels");
163
164 m_junkFraction = new TH1F("TOP/junkFraction", "Fraction of junk hits per boardstack", 64, 0.5, 16.5);
165 m_junkFraction->SetXTitle("slot number");
166 m_junkFraction->SetYTitle("fraction");
167 // note: titles are intentionally the same since this one is plotted first
168 m_excludedBSHisto = new TH1F("TOP/excludedBSHisto", "Fraction of junk hits per boardstack", 64, 0.5, 16.5);
169 m_excludedBSHisto->SetXTitle("slot number");
170 m_excludedBSHisto->SetYTitle("fraction");
171 m_c_junkFraction = new TCanvas("TOP/c_junkFraction", "c_junkFraction");
172
173 for (int slot = 1; slot <= 16; slot++) {
174 string hname = "TOP/pmtHitRates_" + to_string(slot);
175 string htitle = "PMT hits per event for slot #" + to_string(slot);
176 auto* h = new TH1F(hname.c_str(), htitle.c_str(), 32, 0.5, 32.5);
177 h->SetXTitle("PMT number");
178 h->SetYTitle("Number of good hits per event");
179 m_pmtHitRates.push_back(h);
180 string cname = "TOP/c_pmtHitRates_" + to_string(slot);
181 string ctitle = "c_pmtHitRates_" + to_string(slot);
182 m_c_pmtHitRates.push_back(new TCanvas(cname.c_str(), ctitle.c_str()));
183 }
184
185 m_text1 = new TPaveText(0.125, 0.8, 0.675, 0.88, "NDC");
186 m_text1->SetFillColorAlpha(kWhite, 0);
187 m_text1->SetBorderSize(0);
188 m_text2 = new TPaveText(0.55, 0.8, 0.85, 0.89, "NDC");
189 m_text2->SetFillColorAlpha(kWhite, 0);
190 m_text2->SetBorderSize(0);
191 m_text3 = new TPaveText(0.47, 0.8, 0.85, 0.89, "NDC");
192 m_text3->SetFillColorAlpha(kWhite, 0);
193 m_text3->SetBorderSize(0);
194 m_text4 = new TPaveText(0.125, 0.8, 0.675, 0.88, "NDC");
195 m_text4->SetFillColorAlpha(kWhite, 0);
196 m_text4->SetBorderSize(0);
197
198 for (int slot = 1; slot < 16; slot++) {
199 auto* line = new TLine(slot + 0.5, 0, slot + 0.5, 1);
200 line->SetLineWidth(1);
201 line->SetLineStyle(2);
202 m_verticalLines.push_back(line);
203 }
204
206
207 B2DEBUG(20, "DQMHistAnalysisTOP: initialized.");
208}
209
210
212{
213 m_mirabelleVariables.clear();
214
215 // open the reference file and get reference histograms (closed and map cleared in endRun)
216 m_refFile = TFile::Open(m_refFileName.c_str());
217 if (m_refFile and m_refFile->IsOpen()) {
218 m_refTimingHisto["default"] = (TH1F*) m_refFile->Get("ref/TOP/default/goodHitTimes");
219 m_refTimingHisto["debug"] = (TH1F*) m_refFile->Get("ref/TOP/debug/goodHitTimes");
220 m_refTimingHisto["physics"] = (TH1F*) m_refFile->Get("ref/TOP/physics/goodHitTimes");
221 m_refTimingHisto["cosmics"] = (TH1F*) m_refFile->Get("ref/TOP/cosmics/goodHitTimes");
222 } else {
223 B2ERROR("Can't open reference file: " << m_refFileName);
224 }
225
226 B2DEBUG(20, "DQMHistAnalysisTOP: beginRun called.");
227}
228
229
231{
232 // get type of the run (TODO: to be replaced with base class function when fixed)
233 auto* rtype = findHist("DQMInfo/rtype");
234 m_runType = rtype ? rtype->GetTitle() : "";
235 m_IsNullRun = (m_runType == "null");
236
237 // get number of events processed with TOPDQM module
238 auto* goodHitsPerEvent = findHist("TOP/goodHitsPerEventAll");
239 m_numEvents = goodHitsPerEvent ? goodHitsPerEvent->GetEntries() : 0;
240
241 bool zeroSupp = gStyle->GetHistMinimumZero();
242 gStyle->SetHistMinimumZero(true);
243
244 // update alarm levels and other parameters from EpicsPVs
245 updateLimits();
246
247 // reset overall alarm state
248 m_alarmStateOverall = c_Gray;
249
250 // Update window_vs_slot canvas w/ alarming
252
253 // Update event desynchronization monitor w/ alarming
255
256 // Update number of good hits per event w/ alarming (injection BG)
258
259 // Update event T0 w/ alarming
261
262 // Update bunch offset w/ alarming
264
265 // Fraction of dead and hot channels
266 const auto* activeFraction = makeDeadAndHotFractionsPlot();
267
268 // Photon yields and background rates, corrected for dead and hot channels
269 makePhotonYieldsAndBGRatePlots(activeFraction);
270
271 // Fractions of junk hits
273
274 // Set z-axis range to 3 times the average for good hits, 30 times the average for junk hits
275 setZAxisRange("TOP/good_hits_xy_", 3);
276 setZAxisRange("TOP/bad_hits_xy_", 30);
277 setZAxisRange("TOP/good_hits_asics_", 3);
278 setZAxisRange("TOP/bad_hits_asics_", 30);
279
280 // Background subtracted time distributions (only for physics runs)
281 if (m_runType == "physics") {
282 auto* trackHits = (TH2F*) findHist("TOP/trackHits");
283 makeBGSubtractedTimingPlot("goodHitTimes", trackHits, 0);
284 for (int slot = 1; slot <= 16; slot++) {
285 makeBGSubtractedTimingPlot("good_timing_" + to_string(slot), trackHits, slot);
286 }
287 }
288
289 // Update timing plot w/ alarming
291
292 // PMT hit rates
294
295 // Set Epics variables
297
298 gStyle->SetHistMinimumZero(zeroSupp);
299}
300
301
303{
304 // these two histograms do not exist anymore since file is closed, therefore
305 m_photonYields = nullptr;
306 m_backgroundRates = nullptr;
307
308 // add MiraBelle monitoring
309
310 for (const auto& var : m_mirabelleVariables) {
311 m_monObj->setVariable(var.first, var.second);
312 B2DEBUG(20, var.first << " " << var.second);
313 }
314
315 // close the reference file and clear the histogram container
316 if (m_refFile and m_refFile->IsOpen()) m_refFile->Close();
317 m_refTimingHisto.clear();
318
319 B2DEBUG(20, "DQMHistAnalysisTOP : endRun called");
320}
321
322
324{
325 B2DEBUG(20, "terminate called");
326}
327
328
330{
331 int alarmState = c_Gray;
332 m_text1->Clear();
333
334 auto* hraw = (TH2F*) findHist("TOP/window_vs_slot");
335 if (hraw) {
336 auto* px = hraw->ProjectionX("tmp_px");
337 auto* band = hraw->ProjectionX("TOP/windowFractions", m_asicWindowsBand[0], m_asicWindowsBand[1]);
338 band->Add(px, band, 1, -1);
339 double total = px->Integral();
340 double totalWindowFraction = (total != 0) ? band->Integral() / total : 0;
341 band->Divide(band, px);
342 setMiraBelleVariables("RateBadRaw_slot", band);
343 m_mirabelleVariables["RateBadRaw_all"] = totalWindowFraction;
344 if (total > 0) {
345 alarmState = getAlarmState(totalWindowFraction, m_asicWindowsAlarmLevels);
346 m_text1->AddText(Form("Fraction outside red lines: %.2f %%", totalWindowFraction * 100.0));
347 }
348 delete px;
349 delete band;
350 }
351
352 m_alarmStateOverall = std::max(m_alarmStateOverall, alarmState);
353
354 auto* canvas = findCanvas("TOP/c_window_vs_slot");
355 if (canvas) {
356 canvas->Clear();
357 canvas->cd();
358 if (hraw) hraw->Draw();
359 m_text1->Draw();
360 for (auto* line : m_asicWindowsBandLines) line->Draw();
361 canvas->Pad()->SetFrameFillColor(10);
362 canvas->Pad()->SetFillColor(getAlarmColor(alarmState));
363 canvas->Modified();
364 }
365}
366
367
369{
370 int alarmState = c_Gray;
371 m_text2->Clear();
372
373 auto* evtMonitor = (TH1F*) findHist("TOP/BoolEvtMonitor");
374 if (evtMonitor) {
375 double totalEvts = evtMonitor->Integral();
376 double badEvts = evtMonitor->GetBinContent(2);
377 if (totalEvts > 0) {
378 double badRatio = badEvts / totalEvts;
379 alarmState = getAlarmState(badRatio, m_eventMonitorAlarmLevels);
380 m_text2->AddText(Form("Fraction: %.4f %%", badRatio * 100.0));
381 }
382 }
383
384 m_alarmStateOverall = std::max(m_alarmStateOverall, alarmState);
385
386 auto* canvas = findCanvas("TOP/c_BoolEvtMonitor");
387 if (canvas) {
388 canvas->cd();
389 m_text2->Draw();
390 canvas->Pad()->SetFrameFillColor(10);
391 canvas->Pad()->SetFillColor(getAlarmColor(alarmState));
392 canvas->Modified();
393 }
394}
395
396
398{
399 int alarmState = c_Gray;
400 m_text4->Clear();
401
402 double fract = 0;
403 double xcut = 0;
404 double ymax = 0;
405 auto* h = (TH1F*) findHist("TOP/goodHitsPerEventAll");
406 if (h) {
407 double totalEvts = h->GetEntries();
408 if (totalEvts > 1000) {
409 // fraction of events with more than xcut hits - these are mostly containing injection BG
410 xcut = h->GetBinCenter(h->GetMaximumBin()) + 900;
411 ymax = h->GetMaximum() / 2;
412 fract = h->Integral(h->FindBin(xcut), h->GetNbinsX() + 1) / totalEvts * 100; // in %
413 alarmState = getAlarmState(fract, m_injectionBGAlarmLevels);
414 m_text4->AddText(Form("Events w/ Injection BG: %.2f %%", fract));
415 }
416 }
417
418 setEpicsPV("injectionBGAlarmLevels", fract);
419 m_alarmStateOverall = std::max(m_alarmStateOverall, alarmState);
420
421 auto* canvas = findCanvas("TOP/c_goodHitsPerEventAll");
422 if (canvas) {
423 canvas->cd();
424 if (not m_injBGCutLine) {
425 m_injBGCutLine = new TLine(xcut, 0, xcut, ymax);
426 m_injBGCutLine->SetLineWidth(2);
427 m_injBGCutLine->SetLineColor(kRed);
428 m_injBGCutLine->Draw("same");
429 } else {
430 m_injBGCutLine->SetX1(xcut);
431 m_injBGCutLine->SetX2(xcut);
432 m_injBGCutLine->SetY2(ymax);
433 }
434 m_text4->Draw();
435 canvas->Pad()->SetFrameFillColor(10);
436 canvas->Pad()->SetFillColor(getAlarmColor(alarmState));
437 canvas->Modified();
438 }
439}
440
441
443{
444 int alarmState = c_Gray;
445
446 auto* h = (TH1F*) findHist("TOP/eventT0");
447 if (h) {
448 double totalEvts = h->GetEntries();
449 if (totalEvts > 100) {
450 double mean = h->GetMean();
451 double rms = h->GetRMS();
452 alarmState = std::max(getAlarmState(fabs(mean), m_eventT0MeanAlarmLevels), getAlarmState(rms, m_eventT0RmsAlarmLevels));
453 }
454 }
455
456 m_alarmStateOverall = std::max(m_alarmStateOverall, alarmState);
457
458 auto* canvas = findCanvas("TOP/c_eventT0");
459 if (canvas) {
460 canvas->cd();
461 canvas->Pad()->SetFrameFillColor(10);
462 canvas->Pad()->SetFillColor(getAlarmColor(alarmState));
463 canvas->Modified();
464 }
465}
466
467
469{
470 int alarmState = c_Gray;
471
472 auto* h = (TH1F*) findHist("TOP/bunchOffset");
473 if (h) {
474 double totalEvts = h->GetEntries();
475 if (totalEvts > 100) {
476 double mean = h->GetMean();
477 double rms = h->GetRMS();
478 alarmState = std::max(getAlarmState(fabs(mean), m_offsetMeanAlarmLevels), getAlarmState(rms, m_offsetRmsAlarmLevels));
479 }
480 }
481
482 m_alarmStateOverall = std::max(m_alarmStateOverall, alarmState);
483
484 auto* canvas = findCanvas("TOP/c_bunchOffset");
485 if (canvas) {
486 canvas->cd();
487 canvas->Pad()->SetFrameFillColor(10);
488 canvas->Pad()->SetFillColor(getAlarmColor(alarmState));
489 canvas->Modified();
490 }
491}
492
493
495{
496 int alarmState = c_Gray;
497
498 auto* h = (TH1F*) findHist("TOP/goodHitTimes");
499 TH1F* href = nullptr;
500 if (m_refFile and m_refFile->IsOpen()) {
501 auto it = m_refTimingHisto.find(m_runType);
502 href = (it != m_refTimingHisto.end()) ? it->second : m_refTimingHisto["default"];
503 }
504 if (h and href) {
505 double n = h->Integral();
506 double nref = href->Integral();
507 if (n > 0 and nref > 0 and sameHistDefinition(h, href)) {
508 auto* h_clone = (TH1F*) h->Clone("tmp");
509 auto* href_clone = (TH1F*) href->Clone("tmpref");
510 h_clone->Scale(1 / n);
511 href_clone->Scale(1 / nref);
512 h_clone->Add(h_clone, href_clone, 1, -1);
513 double sumDiff = 0;
514 double errDiff = 0;
515 for (int i = 1; i <= h_clone->GetNbinsX(); i++) {
516 sumDiff += fabs(h_clone->GetBinContent(i));
517 errDiff += pow(h_clone->GetBinError(i), 2);
518 }
519 errDiff = sqrt(errDiff);
520 if (sumDiff < 5 * errDiff) sumDiff = 0; // difference not significant
521 alarmState = getAlarmState(sumDiff, m_timingAlarmLevels);
522 delete h_clone;
523 delete href_clone;
524 }
525 }
526
527 m_alarmStateOverall = std::max(m_alarmStateOverall, alarmState);
528
529 auto* canvas = findCanvas("TOP/c_goodHitTimes");
530 if (canvas) {
531 canvas->cd();
532 canvas->Pad()->SetFrameFillColor(10);
533 canvas->Pad()->SetFillColor(getAlarmColor(alarmState));
534 canvas->Modified();
535 }
536}
537
539{
540 if (h1->GetNbinsX() != h2->GetNbinsX()) return false;
541 if (h1->GetXaxis()->GetXmin() != h2->GetXaxis()->GetXmin()) return false;
542 if (h1->GetXaxis()->GetXmax() != h2->GetXaxis()->GetXmax()) return false;
543 return true;
544}
545
547{
548 m_deadFraction->Reset();
549 m_hotFraction->Reset();
550 m_excludedFraction->Reset();
551 m_activeFraction->Reset();
552 double inactiveFract = 0; // max inactive channel fraction when some boardstacks are excluded from alarming
553
554 for (int slot = 1; slot <= 16; slot++) {
555 auto* h = (TH1F*) findHist("TOP/good_channel_hits_" + std::to_string(slot));
556 if (not h) continue;
557
558 auto cuts = getDeadAndHotCuts(h);
559 double deadCut = cuts.first;
560 double hotCut = cuts.second;
561 double deadFract = 0;
562 double hotFract = 0;
563 double deadFractIncl = 0;
564 double hotFractIncl = 0;
565 for (int chan = 0; chan < h->GetNbinsX(); chan++) {
566 double y = h->GetBinContent(chan + 1);
567 int bs = chan / 128 + (slot - 1) * 4;
568 bool included = m_includedBoardstacks[bs];
569 if (y <= deadCut) {
570 deadFract += 1;
571 if (included) deadFractIncl += 1;
572 } else if (y > hotCut) {
573 hotFract += 1;
574 if (included) hotFractIncl += 1;
575 }
576 }
577 deadFract /= h->GetNbinsX();
578 hotFract /= h->GetNbinsX();
579 deadFractIncl /= h->GetNbinsX();
580 hotFractIncl /= h->GetNbinsX();
581 m_deadFraction->SetBinContent(slot, deadFractIncl);
582 m_hotFraction->SetBinContent(slot, hotFractIncl);
583 m_excludedFraction->SetBinContent(slot, deadFract - deadFractIncl + hotFract - hotFractIncl);
584 m_activeFraction->SetBinContent(slot, 1 - deadFract - hotFract);
585 inactiveFract = std::max(inactiveFract, deadFractIncl + hotFractIncl);
586 }
587
588 setMiraBelleVariables("ActiveChannelFraction_slot", m_activeFraction);
589
590 int alarmState = c_Gray;
591 if (m_activeFraction->Integral() > 0) {
592 alarmState = getAlarmState(inactiveFract, m_deadChannelsAlarmLevels);
593 }
594
595 m_alarmStateOverall = std::max(m_alarmStateOverall, alarmState);
596
597 m_deadFraction->SetFillColor(1);
598 m_deadFraction->SetLineColor(1);
599 m_deadFraction->GetXaxis()->SetNdivisions(16);
600
601 m_hotFraction->SetFillColor(2);
602 m_hotFraction->SetLineColor(2);
603 m_hotFraction->GetXaxis()->SetNdivisions(16);
604
605 m_excludedFraction->SetFillColor(kGray);
606 m_excludedFraction->SetLineColor(kGray);
607 m_excludedFraction->GetXaxis()->SetNdivisions(16);
608
609 m_activeFraction->SetFillColor(0);
610 m_activeFraction->GetXaxis()->SetNdivisions(16);
611
612 auto* canvas = m_c_deadAndHot;
613 canvas->Clear();
614 canvas->cd();
615 canvas->Pad()->SetFrameFillColor(10);
616 if (not m_stack) {
617 m_stack = new THStack("TOP/stack", "Fraction of dead and hot channels");
622 }
623 m_stack->Draw();
624
625 for (auto* line : m_deadChannelsAlarmLines) line->Draw("same");
626
627 if (not m_legend) {
628 m_legend = new TLegend(0.8, 0.87, 0.99, 0.99);
629 m_legend->AddEntry(m_hotFraction, "hot");
630 m_legend->AddEntry(m_deadFraction, "dead");
631 m_legend->AddEntry(m_excludedFraction, "excluded");
632 }
633 m_legend->Draw("same");
634
635 canvas->Pad()->SetFillColor(getAlarmColor(alarmState));
636 canvas->Modified();
637
638 return m_activeFraction;
639}
640
641
643{
644 for (auto* canvas : {m_c_photonYields, m_c_backgroundRates}) {
645 canvas->Clear();
646 canvas->Pad()->SetFrameFillColor(10);
647 canvas->Pad()->SetFillColor(getAlarmColor(c_Gray));
648 canvas->Modified();
649 }
650 m_averageRate = 0;
651
652 auto* signalHits = (TProfile*) findHist("TOP/signalHits");
653 if (not signalHits) return;
654
655 auto* backgroundHits = (TProfile*) findHist("TOP/backgroundHits");
656 if (not backgroundHits) return;
657
658 if (m_photonYields) delete m_photonYields;
659 m_photonYields = signalHits->ProjectionX("TOP/photonYields");
661 m_backgroundRates = backgroundHits->ProjectionX("TOP/backgroundRates");
662 auto* activeFract = (TH1F*) activeFraction->Clone("tmp");
663 for (int i = 1; i <= activeFract->GetNbinsX(); i++) activeFract->SetBinError(i, 0);
664
666 m_photonYields->Divide(m_photonYields, activeFract);
667 setMiraBelleVariables("PhotonsPerTrack_slot", m_photonYields);
668
669 int alarmState = c_Gray;
670 if (signalHits->GetEntries() > 0 and activeFraction->Integral() > 0) {
671 double hmin = 1000;
672 for (int i = 1; i <= m_photonYields->GetNbinsX(); i++) {
673 if (signalHits->GetBinEntries(i) < 10) continue;
674 hmin = std::min(hmin, m_photonYields->GetBinContent(i) + 3 * m_photonYields->GetBinError(i));
675 }
676 if (hmin < 1000) alarmState = getAlarmState(hmin, m_photonYieldsAlarmLevels, false);
677 }
678 m_alarmStateOverall = std::max(m_alarmStateOverall, alarmState);
679
680 m_photonYields->SetTitle("Number of photons per track");
681 m_photonYields->SetYTitle("photons per track");
682 m_photonYields->SetMarkerStyle(24);
683 m_photonYields->GetXaxis()->SetNdivisions(16);
684
685 auto* canvas = m_c_photonYields;
686 canvas->cd();
687 m_photonYields->SetMinimum(0);
688 m_photonYields->Draw();
689 for (auto* line : m_photonYieldsAlarmLines) line->Draw("same");
690 canvas->Pad()->SetFillColor(getAlarmColor(alarmState));
691 canvas->Modified();
692
693 m_backgroundRates->Scale(1.0 / 50.0e-3 / 32); // measured in 50 ns window, 32 PMT's ==> rate in MHz/PMT
694 m_backgroundRates->Divide(m_backgroundRates, activeFract);
695 setMiraBelleVariables("BackgroundRate_slot", m_backgroundRates);
696
697 alarmState = c_Gray;
698 m_text3->Clear();
699 if (backgroundHits->GetEntries() > 100 and activeFraction->Integral() > 0) {
700 int status = m_backgroundRates->Fit("pol0", "Q0");
701 if (status == 0) {
702 auto* fun = m_backgroundRates->GetFunction("pol0");
703 if (fun) {
704 m_averageRate = fun->GetParameter(0);
705 double error = fun->GetParError(0);
706 alarmState = getAlarmState(m_averageRate - 3 * error, m_backgroundAlarmLevels);
707 m_text3->AddText(Form("Average: %.2f MHz/PMT", m_averageRate));
708 }
709 }
710 }
711 m_alarmStateOverall = std::max(m_alarmStateOverall, alarmState);
712
713 m_backgroundRates->SetTitle("Background rates");
714 m_backgroundRates->SetYTitle("background rate [MHz/PMT]");
715 m_backgroundRates->SetMarkerStyle(24);
716 m_backgroundRates->GetXaxis()->SetNdivisions(16);
717
718 canvas = m_c_backgroundRates;
719 canvas->cd();
720 m_backgroundRates->SetMinimum(0);
721 m_backgroundRates->Draw();
722 for (auto* line : m_backgroundAlarmLines) line->Draw("same");
723 m_text3->Draw();
724 canvas->Pad()->SetFillColor(getAlarmColor(alarmState));
725 canvas->Modified();
726
727 delete activeFract;
728}
729
730
732{
733 m_junkFraction->Reset();
734 m_excludedBSHisto->Reset();
735 auto* allHits = (TH1D*) m_junkFraction->Clone("tmp");
736 for (int slot = 1; slot <= 16; slot++) {
737 auto* good = (TH1F*) findHist("TOP/good_channel_hits_" + std::to_string(slot));
738 if (not good) continue;
739 auto* bad = (TH1F*) findHist("TOP/bad_channel_hits_" + std::to_string(slot));
740 if (not bad) continue;
741 for (int i = 0; i < 512; i++) {
742 int bs = i / 128;
743 allHits->Fill(slot + bs / 4. - 0.5, good->GetBinContent(i + 1) + bad->GetBinContent(i + 1));
744 m_junkFraction->Fill(slot + bs / 4. - 0.5, bad->GetBinContent(i + 1));
745 }
746 }
747
748 m_junkFraction->Divide(m_junkFraction, allHits, 1, 1, "B");
749
750 int alarmState = c_Gray;
751 if (allHits->Integral() > 0) {
752 double hmax = 0;
753 for (size_t i = 0; i < m_includedBoardstacks.size(); i++) {
754 if (m_includedBoardstacks[i]) hmax = std::max(hmax, m_junkFraction->GetBinContent(i + 1));
755 else m_excludedBSHisto->SetBinContent(i + 1, 1);
756 }
757 alarmState = getAlarmState(hmax, m_junkHitsAlarmLevels);
758 }
759 delete allHits;
760 m_alarmStateOverall = std::max(m_alarmStateOverall, alarmState);
761
762 auto* canvas = m_c_junkFraction;
763 canvas->Clear();
764 canvas->cd();
765 canvas->Pad()->SetFrameFillColor(10);
766 canvas->Pad()->SetFillColor(getAlarmColor(alarmState));
767 m_excludedBSHisto->SetFillColor(kGray);
768 m_excludedBSHisto->SetLineColor(kGray);
769 m_excludedBSHisto->GetXaxis()->SetNdivisions(16);
770 m_excludedBSHisto->GetYaxis()->SetRangeUser(0, 1);
771 m_excludedBSHisto->Draw();
772 m_junkFraction->SetMarkerStyle(24);
773 m_junkFraction->GetXaxis()->SetNdivisions(16);
774 m_junkFraction->GetYaxis()->SetRangeUser(0, 1); // Note: m_junkFraction->GetMaximum() will now give 1 and not the histogram maximum!
775 m_junkFraction->Draw("same");
776 for (auto* line : m_verticalLines) line->Draw("same");
777 for (auto* line : m_junkHitsAlarmLines) line->Draw("same");
778 canvas->Modified();
779}
780
781
782void DQMHistAnalysisTOPModule::setZAxisRange(const std::string& name, double scale)
783{
784 double totalHits = 0;
785 std::vector<TH2F*> histos;
786 for (int slot = 1; slot <= 16; slot++) {
787 TH2F* h = (TH2F*) findHist(name + std::to_string(slot));
788 if (not h) continue;
789 histos.push_back(h);
790 totalHits += h->Integral();
791 }
792 if (histos.empty()) return;
793 double average = totalHits / 512 / histos.size(); // per pixel or asic channel
794
795 for (auto* h : histos) h->GetZaxis()->SetRangeUser(0, std::max(average * scale, 1.0));
796}
797
798
799void DQMHistAnalysisTOPModule::makeBGSubtractedTimingPlot(const std::string& name, const TH2F* trackHits, int slot)
800{
801 auto* canvas = findCanvas("TOP/c_" + name);
802 if (not canvas) return;
803
804 auto* h = (TH1F*) findHist("TOP/" + name);
805 if (not h) return;
806
807 auto* hb = (TH1F*) findHist("TOP/" + name + "BG");
808 if (not hb) return;
809
810 if (trackHits) {
811 // use the ratio of events w/ and w/o track in the slot to scale the background
812 double s = (slot == 0) ? trackHits->Integral(1, 16, 2, 2) : trackHits->GetBinContent(slot, 2);
813 if (s == 0) return;
814 double sb = (slot == 0) ? trackHits->Integral(1, 16, 1, 1) : trackHits->GetBinContent(slot, 1);
815 if (sb == 0) return;
816 h->Add(h, hb, 1, -s / sb);
817 } else {
818 // use the content of bins at t < 0 to scale the background
819 int i0 = h->GetXaxis()->FindBin(0.); // bin at t = 0
820 double s = h->Integral(1, i0);
821 if (s == 0) return;
822 double sb = hb->Integral(1, i0);
823 if (sb == 0) return;
824 if (s / sb > 1) return; // this can happen due to low statistics and is not reliable
825 h->Add(h, hb, 1, -s / sb);
826 }
827
828 TString title = TString(h->GetTitle()) + " (BG subtracted)";
829 h->SetTitle(title);
830
831 canvas->Clear();
832 canvas->cd();
833 h->Draw();
834 canvas->Modified();
835}
836
837
839{
840 auto* h0 = (TH1F*) findHist("TOP/goodHitsPerEventAll");
841 if (not h0) return;
842 double numEvents = h0->GetEntries();
843 if (numEvents == 0) return;
844
845 int numSlots = m_pmtHitRates.size();
846 for (int slot = 1; slot <= numSlots; slot++) {
847 string name = "TOP/good_hits_xy_" + to_string(slot);
848 auto* hxy = (TH2F*) findHist(name);
849 if (not hxy) continue;
850 std::vector<double> pmts(32, 0);
851 for (int row = 0; row < 8; row++) {
852 for (int col = 0; col < 64; col++) {
853 int pmt = col / 4 + (row / 4) * 16;
854 pmts[pmt] += hxy->GetBinContent(col + 1, row + 1);
855 }
856 }
857 auto* h = m_pmtHitRates[slot - 1];
858 for (size_t i = 0; i < pmts.size(); i++) {
859 h->SetBinContent(i + 1, pmts[i] / numEvents);
860 }
861 auto* canvas = m_c_pmtHitRates[slot - 1];
862 canvas->Clear();
863 canvas->cd();
864 h->SetMinimum(0);
865 h->Draw();
866 canvas->Modified();
867 }
868}
869
870
871void DQMHistAnalysisTOPModule::setMiraBelleVariables(const std::string& variableName, const TH1* histogram)
872{
873 for (int slot = 1; slot <= 16; slot++) {
874 auto vname = variableName + std::to_string(slot);
875 double value = histogram ? histogram->GetBinContent(slot) : 0;
876 m_mirabelleVariables[vname] = value;
877 }
878}
879
880
881int DQMHistAnalysisTOPModule::getAlarmState(double value, const std::vector<double>& alarmLevels, bool bigRed) const
882{
883 if (m_IsNullRun or m_numEvents < 1000) return c_Gray;
884
885 if (bigRed) {
886 if (value < alarmLevels[0]) return c_Green;
887 else if (value < alarmLevels[1]) return c_Yellow;
888 else return c_Red;
889 } else {
890 if (value < alarmLevels[0]) return c_Red;
891 else if (value < alarmLevels[1]) return c_Yellow;
892 else return c_Green;
893 }
894}
895
896
897void DQMHistAnalysisTOPModule::setAlarmLines(const std::vector<double>& alarmLevels, double xmin, double xmax,
898 std::vector<TLine*>& alarmLines, bool bigRed)
899{
900 std::vector<int> colors = {kOrange, kRed};
901 if (not bigRed) std::reverse(colors.begin(), colors.end());
902 for (size_t i = 0; i < std::min(colors.size(), alarmLevels.size()); i++) {
903 if (i < alarmLines.size()) {
904 auto* line = alarmLines[i];
905 line->SetX1(xmin);
906 line->SetX2(xmax);
907 line->SetY1(alarmLevels[i]);
908 line->SetY2(alarmLevels[i]);
909 } else {
910 auto* line = new TLine(xmin, alarmLevels[i], xmax, alarmLevels[i]);
911 line->SetLineWidth(2);
912 line->SetLineStyle(2);
913 line->SetLineColor(colors[i]);
914 alarmLines.push_back(line);
915 }
916 }
917}
918
919
921{
922 for (size_t i = 0; i < m_asicWindowsBand.size(); i++) {
923 double y = m_asicWindowsBand[i];
924 if (i < m_asicWindowsBandLines.size()) {
925 auto* line = m_asicWindowsBandLines[i];
926 line->SetY1(y);
927 line->SetY2(y);
928 } else {
929 auto* line = new TLine(0.5, y, 16.5, y);
930 line->SetLineWidth(2);
931 line->SetLineColor(kRed);
932 m_asicWindowsBandLines.push_back(line);
933 }
934 }
935
940}
941
942
943std::pair<double, double> DQMHistAnalysisTOPModule::getDeadAndHotCuts(const TH1* h)
944{
945 std::vector<double> binContents;
946 for (int k = 1; k <= h->GetNbinsY(); k++) {
947 for (int i = 1; i <= h->GetNbinsX(); i++) {
948 binContents.push_back(h->GetBinContent(i, k));
949 }
950 }
951
952 double mean = 0;
953 double rms = h->GetMaximum();
954 for (int iter = 0; iter < 5; iter++) {
955 double sumy = 0;
956 double sumyy = 0;
957 int n = 0;
958 for (auto y : binContents) {
959 if (y == 0 or fabs(y - mean) > 3 * rms) continue;
960 sumy += y;
961 sumyy += y * y;
962 n++;
963 }
964 if (n == 0) continue;
965 mean = sumy / n;
966 rms = sqrt(sumyy / n - mean * mean);
967 }
968
969 return std::make_pair(mean / 5, std::max(mean * 2, mean + 6 * rms));
970}
971
972
974{
975 int badBoardstacks = 0;
976 int badCarriers = 0;
977 int badAsics = 0;
978 for (int slot = 1; slot <= 16; slot++) {
979 std::string hname = "TOP/good_hits_asics_" + to_string(slot);
980 auto* h = (TH2F*) findHist(hname);
981 if (not h) continue;
982
983 auto cuts = getDeadAndHotCuts(h);
984 double deadCut = cuts.first;
985 double hotCut = cuts.second;
986 std::vector<int> asics(64, 0);
987 std::vector<int> carriers(16, 0);
988 std::vector<int> boardstacks(4, 0);
989 for (int asic = 0; asic < 64; asic++) {
990 int carrier = asic / 4;
991 int boardstack = carrier / 4;
992 for (int chan = 0; chan < 8; chan++) {
993 double y = h->GetBinContent(asic + 1, chan + 1);
994 if (y > deadCut and y <= hotCut) {
995 asics[asic]++;
996 carriers[carrier]++;
997 boardstacks[boardstack]++;
998 }
999 }
1000 }
1001 for (int n : asics) if (n == 0) badAsics++;
1002 for (int n : carriers) if (n == 0) badCarriers++;
1003 for (int n : boardstacks) if (n == 0) badBoardstacks++;
1004 }
1005 badAsics -= badCarriers * 4;
1006 badCarriers -= badBoardstacks * 4;
1007
1008 int badPMTs = 0;
1009 for (int slot = 1; slot <= 16; slot++) {
1010 std::string hname = "TOP/good_hits_xy_" + to_string(slot);
1011 auto* h = (TH2F*) findHist(hname);
1012 if (not h) continue;
1013
1014 auto cuts = getDeadAndHotCuts(h);
1015 double deadCut = cuts.first;
1016 double hotCut = cuts.second;
1017 std::vector<int> pmts(32, 0);
1018 for (int row = 0; row < 8; row++) {
1019 for (int col = 0; col < 64; col++) {
1020 int pmt = col / 4 + (row / 4) * 16;
1021 double y = h->GetBinContent(col + 1, row + 1);
1022 if (y > deadCut and y <= hotCut) pmts[pmt]++;
1023 }
1024 }
1025 for (int n : pmts) if (n == 0) badPMTs++;
1026 }
1027 badPMTs -= badBoardstacks * 8;
1028
1029 setEpicsPV("badBoardstacks", badBoardstacks);
1030 setEpicsPV("badCarriers", badCarriers);
1031 setEpicsPV("badAsics", badAsics);
1032 setEpicsPV("badPMTs", badPMTs);
1033 int numBS = 0;
1034 for (auto included : m_includedBoardstacks) if (not included) numBS++;
1035 setEpicsPV("numExcludedBS", numBS);
1037 setEpicsPV("backgroundAlarmLevels", m_averageRate);
1038
1039 B2DEBUG(20, "badBoardstacks: " << badBoardstacks);
1040 B2DEBUG(20, "badCarriers: " << badCarriers);
1041 B2DEBUG(20, "badAsics: " << badAsics);
1042 B2DEBUG(20, "badPMTs: " << badPMTs);
1043 B2DEBUG(20, "excludedBS: " << numBS);
1044 B2DEBUG(20, "histoAlarmState: " << getOffcialAlarmStatus(m_alarmStateOverall));
1045 B2DEBUG(20, "backgroundAlarmLevels" << m_averageRate);
1046}
1047
1049{
1050 double unused = 0;
1051
1052 double yLo = m_asicWindowsBand[0];
1053 double yHi = m_asicWindowsBand[1];
1054 requestLimitsFromEpicsPVs("asicWindowsBand", yLo, unused, unused, yHi);
1055 m_asicWindowsBand[0] = yLo;
1056 m_asicWindowsBand[1] = yHi;
1057
1058 requestLimitsFromEpicsPVs("asicWindowsAlarmLevels", unused, unused, m_asicWindowsAlarmLevels[0], m_asicWindowsAlarmLevels[1]);
1059 requestLimitsFromEpicsPVs("eventMonitorAlarmLevels", unused, unused, m_eventMonitorAlarmLevels[0], m_eventMonitorAlarmLevels[1]);
1060 requestLimitsFromEpicsPVs("junkHitsAlarmLevels", unused, unused, m_junkHitsAlarmLevels[0], m_junkHitsAlarmLevels[1]);
1061 requestLimitsFromEpicsPVs("deadChannelsAlarmLevels", unused, unused, m_deadChannelsAlarmLevels[0], m_deadChannelsAlarmLevels[1]);
1062 requestLimitsFromEpicsPVs("backgroundAlarmLevels", unused, unused, m_backgroundAlarmLevels[0], m_backgroundAlarmLevels[1]);
1063 requestLimitsFromEpicsPVs("photonYieldsAlarmLevels", m_photonYieldsAlarmLevels[0], m_photonYieldsAlarmLevels[1], unused, unused);
1064
1065 requestLimitsFromEpicsPVs("injectionBGAlarmLevels", unused, unused, m_injectionBGAlarmLevels[0], m_injectionBGAlarmLevels[1]);
1066 requestLimitsFromEpicsPVs("timingAlarmLevels", unused, unused, m_timingAlarmLevels[0], m_timingAlarmLevels[1]);
1067 requestLimitsFromEpicsPVs("eventT0MeanAlarmLevels", unused, unused, m_eventT0MeanAlarmLevels[0], m_eventT0MeanAlarmLevels[1]);
1068 requestLimitsFromEpicsPVs("eventT0RmsAlarmLevels", unused, unused, m_eventT0RmsAlarmLevels[0], m_eventT0RmsAlarmLevels[1]);
1069 requestLimitsFromEpicsPVs("offsetMeanAlarmLevels", unused, unused, m_offsetMeanAlarmLevels[0], m_offsetMeanAlarmLevels[1]);
1070 requestLimitsFromEpicsPVs("offsetRmsAlarmLevels", unused, unused, m_offsetRmsAlarmLevels[0], m_offsetRmsAlarmLevels[1]);
1071
1072 setAlarmLines();
1073
1074 bool status = false;
1075 std::string excludedBS = getEpicsStringPV("excludedBoardstacks", status);
1076
1077 if (status) {
1078 m_excludedBoardstacks.clear();
1079 std::string name;
1080 for (auto c : excludedBS) {
1081 if (isspace(c)) continue;
1082 else if (ispunct(c)) {
1083 if (not name.empty()) {
1084 m_excludedBoardstacks.push_back(name);
1085 name.clear();
1086 }
1087 } else name.push_back(c);
1088 }
1089 if (not name.empty()) {
1090 m_excludedBoardstacks.push_back(name);
1091 }
1093 }
1094
1095 B2DEBUG(20, "asicWindowsBand: [" << m_asicWindowsBand[0] << ", " << m_asicWindowsBand[1] << "]");
1096 B2DEBUG(20, "asicWindowsAlarmLevels: [" << m_asicWindowsAlarmLevels[0] << ", " << m_asicWindowsAlarmLevels[1] << "]");
1097 B2DEBUG(20, "eventMonitorAlarmLevels: [" << m_eventMonitorAlarmLevels[0] << ", " << m_eventMonitorAlarmLevels[1] << "]");
1098 B2DEBUG(20, "junkHitsAlarmLevels: [" << m_junkHitsAlarmLevels[0] << ", " << m_junkHitsAlarmLevels[1] << "]");
1099 B2DEBUG(20, "deadChannelsAlarmLevels: [" << m_deadChannelsAlarmLevels[0] << ", " << m_deadChannelsAlarmLevels[1] << "]");
1100 B2DEBUG(20, "backgroundAlarmLevels: [" << m_backgroundAlarmLevels[0] << ", " << m_backgroundAlarmLevels[1] << "]");
1101 B2DEBUG(20, "photonYieldsAlarmLevels: [" << m_photonYieldsAlarmLevels[0] << ", " << m_photonYieldsAlarmLevels[1] << "]");
1102
1103 B2DEBUG(20, "injectionBGAlarmLevels: [" << m_injectionBGAlarmLevels[0] << ", " << m_injectionBGAlarmLevels[1] << "]");
1104 B2DEBUG(20, "timingAlarmLevels: [" << m_timingAlarmLevels[0] << ", " << m_timingAlarmLevels[1] << "]");
1105 B2DEBUG(20, "eventT0MeanAlarmLevels: [" << m_eventT0MeanAlarmLevels[0] << ", " << m_eventT0MeanAlarmLevels[1] << "]");
1106 B2DEBUG(20, "eventT0RmsAlarmLevels: [" << m_eventT0RmsAlarmLevels[0] << ", " << m_eventT0RmsAlarmLevels[1] << "]");
1107 B2DEBUG(20, "offsetMeanAlarmLevels: [" << m_offsetMeanAlarmLevels[0] << ", " << m_offsetMeanAlarmLevels[1] << "]");
1108 B2DEBUG(20, "offsetRmsAlarmLevels: [" << m_offsetRmsAlarmLevels[0] << ", " << m_offsetRmsAlarmLevels[1] << "]");
1109
1110 std::string ss;
1111 for (const auto& s : m_excludedBoardstacks) ss += "'" + s + "', ";
1112 if (ss.size() > 2) {ss.pop_back(); ss.pop_back();}
1113 B2DEBUG(20, "excludedBoardstacks: [" << ss << "]");
1114
1115}
1116
1117void DQMHistAnalysisTOPModule::setIncludedBoardstacks(const std::vector<std::string>& excludedBoardstacks)
1118{
1119 m_includedBoardstacks.clear();
1120 m_includedBoardstacks.resize(64, true);
1121
1122 for (const auto& bsname : excludedBoardstacks) {
1123 int id = m_bsmap[bsname];
1124 if (id > 0) m_includedBoardstacks[id - 1] = false;
1125 else B2ERROR("Invalid boardstack name: " << bsname);
1126 }
1127}
The base class for the histogram analysis module.
TCanvas * findCanvas(TString cname)
Find canvas by name.
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).
std::string getEpicsStringPV(std::string keyname, bool &status)
Read value from a EPICS PV.
void setEpicsPV(std::string keyname, double value)
Write value to a EPICS PV.
int registerEpicsPV(std::string pvname, std::string keyname="")
EPICS related Functions.
bool requestLimitsFromEpicsPVs(chid id, double &lowerAlarm, double &lowerWarn, double &upperWarn, double &upperAlarm)
Get Alarm Limits from EPICS PV.
void updateEventMonitorCanvas()
Updates canvas of event desynchronization monitor w/ alarming.
std::vector< int > m_asicWindowsBand
lower and upper bin of a band denoting good windows
std::string m_refFileName
file name of reference histograms
void setZAxisRange(const std::string &name, double scale)
Sets z-axis range of 2D histograms.
TCanvas * m_c_photonYields
Canvas: photon yields per slot.
std::vector< double > m_offsetRmsAlarmLevels
alarm levels for r.m.s.
void initialize() override final
Initializer.
void makePMTHitRatesPlots()
Makes plots of the number of PMT hits per event.
TH1F * m_excludedFraction
fraction of dead and hot channels per slot in excluded boardstacks only
void updateEventT0Canvas()
Updates canvas of event T0 w/ alarming.
std::vector< double > m_deadChannelsAlarmLevels
alarm levels for the fraction of dead + hot channels
std::vector< double > m_asicWindowsAlarmLevels
alarm levels for fraction of windows outside the band
TPaveText * m_text2
text to be written to event desynchonization monitor
TCanvas * m_c_junkFraction
Canvas: fraction of junk hits per boardstack.
THStack * m_stack
stack for drawing dead, hot and active channel fractions
const TH1F * makeDeadAndHotFractionsPlot()
Makes a plot of dead and hot channel fractions per slot.
void makeBGSubtractedTimingPlot(const std::string &name, const TH2F *trackHits, int slot)
Makes background subtracted time distribution plot.
void updateTimingCanvas()
Updates canvas of timing plot w/ alarming.
TPaveText * m_text3
text to be written to background rates
std::vector< TLine * > m_deadChannelsAlarmLines
lines representing alarm levels
std::vector< TCanvas * > m_c_pmtHitRates
Canvases of PMT hits per event (index = slot - 1)
int m_alarmStateOverall
overall alarm state of histograms to be sent by EpicsPV
TPaveText * m_text1
text to be written to window_vs_slot
std::vector< TLine * > m_photonYieldsAlarmLines
lines representing alarm levels
std::pair< double, double > getDeadAndHotCuts(const TH1 *h)
Returns cut levels for dead and hot channels.
std::vector< double > m_offsetMeanAlarmLevels
alarm levels for mean of bunch offset [ns]
std::vector< bool > m_includedBoardstacks
boardstacks included in alarming
bool sameHistDefinition(TH1 *h1, TH1 *h2)
Checks if histograms are defined in the same way (nbins, xmin, xmax)
TPaveText * m_text4
text to be written to number of good hits per event
std::vector< TLine * > m_verticalLines
vertical lines splitting slots
std::string m_pvPrefix
Epics PV prefix.
TH1D * m_photonYields
photon yields per slot
TH1D * m_backgroundRates
background rates per slot
MonitoringObject * m_monObj
MiraBelle monitoring object.
TCanvas * m_c_backgroundRates
Canvas: background rates per slot.
std::vector< double > m_eventMonitorAlarmLevels
alarm levels for fraction of desynchronized digits
void terminate() override final
This method is called at the end of the event processing.
std::map< std::string, double > m_mirabelleVariables
variables for MiraBelle
void setAlarmLines()
Sets all alarm lines.
TH1F * m_activeFraction
fraction of active channels per slot
int getAlarmColor(unsigned alarmState) const
Converts alarm state to color.
std::vector< double > m_eventT0MeanAlarmLevels
alarm levels for mean of event T0 [ns]
void event() override final
This method is called for each event.
std::vector< double > m_photonYieldsAlarmLevels
alarm levels for the number of photons per track
std::vector< TLine * > m_junkHitsAlarmLines
lines representing alarm levels
void setIncludedBoardstacks(const std::vector< std::string > &excludedBoardstacks)
Sets flags for boardstacks to be included in alarming.
std::vector< double > m_injectionBGAlarmLevels
alarm levels for injection background (in % of events)
TH1F * m_deadFraction
fraction of dead channels per slot (included boardstacks only)
double m_averageRate
average BG rate (to pass to EpicsPV)
TH1F * m_hotFraction
fraction of hot channels per slot (included boardstacks only)
std::vector< std::string > m_excludedBoardstacks
list of boarstacks to be excluded from alarming
void makePhotonYieldsAndBGRatePlots(const TH1F *activeFraction)
Make plots of dead-and-hot-channel corrected photon yields and BG rates per slot.
TH1F * m_junkFraction
fraction of junk hits per boardstack
void endRun() override final
This method is called if the current run ends.
int getAlarmState(double value, const std::vector< double > &alarmLevels, bool bigRed=true) const
Returns alarm state.
std::vector< double > m_eventT0RmsAlarmLevels
alarm levels for r.m.s.
std::vector< TLine * > m_asicWindowsBandLines
lines denoting a band of good windows
void makeJunkFractionPlot()
Makes a plot of fractions of junk hits per boardstack.
void beginRun() override final
Called when entering a new run.
TLegend * m_legend
legend for dead and hot channels
TCanvas * m_c_deadAndHot
Canvas: fractin of dead and hot channels.
std::vector< TLine * > m_backgroundAlarmLines
lines representing alarm levels
void updateWindowVsSlotCanvas()
Updates canvas of window_vs_slot w/ alarming.
double m_numEvents
number of events processed with TOPDQM module
std::map< std::string, int > m_bsmap
a map of boardstack names to ID's
std::vector< double > m_backgroundAlarmLevels
alarm levels for background rates [MHz/PMT]
void updateBunchOffsetCanvas()
Updates canvas of bunch offset w/ alarming.
void setEpicsVariables()
Calculates and sets epics variables.
std::vector< double > m_junkHitsAlarmLevels
alarm levels for the fraction of junk hits
bool m_IsNullRun
Run type flag for null runs.
void updateNGoodHitsCanvas()
Updates canvas of number of good hits per event w/ alarming (injection BG)
TLine * m_injBGCutLine
a line denoting the cut on the number of hits for injection BG counting
std::vector< double > m_timingAlarmLevels
alarm levels for time distribution (fraction of area difference)
std::map< std::string, TH1F * > m_refTimingHisto
timing reference histograms for different run types
int getOffcialAlarmStatus(unsigned alarmState) const
Converts alarm state to official status (see EStatus of the base class)
std::vector< TH1F * > m_pmtHitRates
histograms of PMT hits per event (index = slot - 1)
TH1F * m_excludedBSHisto
histogram to show excluded boardstacks on junk fraction plot
void updateLimits()
Updates limits defined by module parameters using EpicsPVs.
TFile * m_refFile
file containing reference histograms
void setMiraBelleVariables(const std::string &variableName, const TH1 *histogram)
Sets MiraBelle variables from the histogram with bins corresponding to slot numbers.
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
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.
STL namespace.