Belle II Software release-09-00-00
DQMHistAnalysis.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// File : DQMHistAnalysisModule.cc
10// Description : Baseclass for DQM histogram analysis module
11//-
12
13#include <dqm/core/DQMHistAnalysis.h>
14#include <boost/algorithm/string.hpp>
15#include <TROOT.h>
16#include <TClass.h>
17
18using namespace std;
19using namespace Belle2;
20
21//-----------------------------------------------------------------
22// Register the Module
23//-----------------------------------------------------------------
24REG_MODULE(DQMHistAnalysis);
25
26//-----------------------------------------------------------------
27// Implementation
28//-----------------------------------------------------------------
29
34#ifdef _BELLE2_EPICS
35std::vector <chid> DQMHistAnalysisModule::m_epicsChID;
36#endif
37
38bool DQMHistAnalysisModule::m_useEpics = false; // default to false, to enable EPICS, add special EPICS Module class into chain
40 false; // special for second "online" use (reading limits). default to false, to enable EPICS, add special EPICS Module parameter
41std::string DQMHistAnalysisModule::m_PVPrefix = "TEST:"; // default to "TEST:", for production, set in EPICS enabler to e.g. "DQM:"
42
44{
45 //Set module properties
46 setDescription("Histogram Analysis module base class");
47}
48
50{
51 s_histList.clear();
52// s_monObjList;
53 s_deltaList.clear();
54 s_canvasUpdatedList.clear();
55}
56
57bool DQMHistAnalysisModule::addHist(const std::string& dirname, const std::string& histname, TH1* h)
58{
59 std::string fullname;
60 if (dirname.size() > 0) {
61 fullname = dirname + "/" + histname;
62 } else {
63 fullname = histname;
64 }
65
66 if (s_histList[fullname].update(h)) {
67 // only if histogram changed, check if delta histogram update needed
68 auto it = s_deltaList.find(fullname);
69 if (it != s_deltaList.end()) {
70 B2DEBUG(20, "Found Delta" << fullname);
71 it->second.update(h); // update
72 }
73 return true; // histogram changed
74 }
75
76 return false; // histogram didnt change
77}
78
79void DQMHistAnalysisModule::addDeltaPar(const std::string& dirname, const std::string& histname, HistDelta::EDeltaType t, int p,
80 unsigned int a)
81{
82 std::string fullname;
83 if (dirname.size() > 0) {
84 fullname = dirname + "/" + histname;
85 } else {
86 fullname = histname;
87 }
88 s_deltaList[fullname].set(t, p, a);
89}
90
91bool DQMHistAnalysisModule::hasDeltaPar(const std::string& dirname, const std::string& histname)
92{
93 std::string fullname;
94 if (dirname.size() > 0) {
95 fullname = dirname + "/" + histname;
96 } else {
97 fullname = histname;
98 }
99 return s_deltaList.find(fullname) != s_deltaList.end(); // contains() if we switch to C++20
100}
101
102TH1* DQMHistAnalysisModule::getDelta(const std::string& dirname, const std::string& histname, int n, bool onlyIfUpdated)
103{
104 std::string fullname;
105 if (dirname.size() > 0) {
106 fullname = dirname + "/" + histname;
107 } else {
108 fullname = histname;
109 }
110 return getDelta(fullname, n, onlyIfUpdated);
111}
112
113TH1* DQMHistAnalysisModule::getDelta(const std::string& fullname, int n, bool onlyIfUpdated)
114{
115 auto it = s_deltaList.find(fullname);
116 if (it != s_deltaList.end()) {
117 return it->second.getDelta(n, onlyIfUpdated);
118 }
119 B2WARNING("Delta hist " << fullname << " not found");
120 return nullptr;
121}
122
124{
125 auto obj = &s_monObjList[objName];
126 obj->SetName(objName.c_str());
127 return obj;
128}
129
130TCanvas* DQMHistAnalysisModule::findCanvas(TString canvas_name)
131{
132 TIter nextkey(gROOT->GetListOfCanvases());
133 TObject* obj{};
134
135 while ((obj = dynamic_cast<TObject*>(nextkey()))) {
136 if (obj->IsA()->InheritsFrom("TCanvas")) {
137 if (obj->GetName() == canvas_name)
138 return dynamic_cast<TCanvas*>(obj);
139 }
140 }
141 return nullptr;
142}
143
144TH1* DQMHistAnalysisModule::findHist(const std::string& histname, bool was_updated)
145{
146 if (s_histList.find(histname) != s_histList.end()) {
147 if (was_updated && !s_histList[histname].isUpdated()) return nullptr;
148 if (s_histList[histname].getHist()) {
149 return s_histList[histname].getHist();
150 } else {
151 B2ERROR("Histogram " << histname << " in histogram list but nullptr.");
152 }
153 }
154 B2INFO("Histogram " << histname << " not in list.");
155 return nullptr;
156}
157
158TH1* DQMHistAnalysisModule::findHist(const std::string& dirname, const std::string& histname, bool updated)
159{
160 if (dirname.size() > 0) {
161 return findHist(dirname + "/" + histname, updated);
162 }
163 return findHist(histname, updated);
164}
165
166TH1* DQMHistAnalysisModule::findHistInCanvas(const std::string& histo_name, TCanvas** cobj)
167{
168
169 TCanvas* cnv = nullptr;
170 // try to get canvas from outside
171 if (cobj) cnv = *cobj;
172 // if no canvas search for it
173 if (cnv == nullptr) {
174 // parse the dir+histo name and create the corresponding canvas name
175 auto s = StringSplit(histo_name, '/');
176 if (s.size() != 2) {
177 B2ERROR("findHistInCanvas: histoname not valid (missing dir?), should be 'dirname/histname': " << histo_name);
178 return nullptr;
179 }
180 auto dirname = s.at(0);
181 auto hname = s.at(1);
182 std::string canvas_name = dirname + "/c_" + hname;
183 cnv = findCanvas(canvas_name);
184 // set canvas pointer for outside
185 if (cnv && cobj) *cobj = cnv;
186 }
187
188 // get histogram pointer
189 if (cnv != nullptr) {
190 TIter nextkey(cnv->GetListOfPrimitives());
191 TObject* obj{};
192 while ((obj = dynamic_cast<TObject*>(nextkey()))) {
193 if (obj->IsA()->InheritsFrom("TH1")) {
194 if (obj->GetName() == histo_name)
195 return dynamic_cast<TH1*>(obj);
196 }
197 }
198 }
199 return nullptr;
200}
201
202TH1* DQMHistAnalysisModule::findHistInFile(TFile* file, const std::string& histname)
203{
204 // find histogram by name in file, histname CAN contain directory!
205 // will return nullptr if file is zeroptr, not found or not correct type
206 if (file && file->IsOpen()) {
207 auto obj = file->Get(histname.data());
208 if (obj != nullptr) {
209 // check class type
210 if (obj->IsA()->InheritsFrom("TH1")) {
211 B2DEBUG(20, "Histogram " << histname << " found in file");
212 return dynamic_cast<TH1*>(obj);
213 } else {
214 B2INFO("Found Object " << histname << " in file is not a histogram");
215 }
216 } else {
217 B2INFO("Histogram " << histname << " not found in file");
218 }
219 }
220 return nullptr;
221}
222
224{
225 if (s_monObjList.find(objName) != s_monObjList.end()) {
226 return &s_monObjList[objName];
227 }
228 B2INFO("MonitoringObject " << objName << " not in memfile.");
229 return NULL;
230}
231
233{
234 double probs[2] = {0.16, 1 - 0.16};
235 double quant[2] = {0, 0};
236 h->GetQuantiles(2, quant, probs);
237 const double sigma68 = (-quant[0] + quant[1]) / 2;
238 return sigma68;
239}
240
241std::vector <std::string> DQMHistAnalysisModule::StringSplit(const std::string& in, const char delim)
242{
243 std::vector <std::string> out;
244 boost::split(out, in, [delim](char c) {return c == delim;});
245 return out;
246}
247
249{
250 TIter nextckey(gROOT->GetListOfCanvases());
251 TObject* cobj = nullptr;
252
253 while ((cobj = dynamic_cast<TObject*>(nextckey()))) {
254 if (cobj->IsA()->InheritsFrom("TCanvas")) {
255 TCanvas* cnv = dynamic_cast<TCanvas*>(cobj);
256 cnv->Clear();
258 }
259 }
260}
261
263{
264 for (auto& it : s_histList) {
265 // attention, we must use reference, otherwise we work on a copy
266 it.second.resetBeforeEvent();
267 }
268 for (auto& it : s_deltaList) {
269 // attention, we must use reference, otherwise we work on a copy
270 it.second.setNotUpdated();
271 }
272
273 s_canvasUpdatedList.clear();
274}
275
277{
278 s_histList.clear();
279}
280
282{
283 for (auto& d : s_deltaList) {
284 d.second.reset();
285 }
286}
287
288void DQMHistAnalysisModule::UpdateCanvas(std::string name, bool updated)
289{
290 s_canvasUpdatedList[name] = updated;
291}
292
293void DQMHistAnalysisModule::UpdateCanvas(TCanvas* c, bool updated)
294{
295 if (c) UpdateCanvas(c->GetName(), updated);
296}
297
298void DQMHistAnalysisModule::ExtractRunType(std::vector <TH1*>& hs)
299{
300 s_runType = "";
301 for (size_t i = 0; i < hs.size(); i++) {
302 if (hs[i]->GetName() == std::string("DQMInfo/rtype")) {
303 s_runType = hs[i]->GetTitle();
304 return;
305 }
306 }
307 B2ERROR("ExtractRunType: Histogram \"DQMInfo/rtype\" missing");
308}
309
310void DQMHistAnalysisModule::ExtractEvent(std::vector <TH1*>& hs)
311{
313 for (size_t i = 0; i < hs.size(); i++) {
314 if (hs[i]->GetName() == std::string("DAQ/Nevent")) {
315 s_eventProcessed = hs[i]->GetEntries();
316 return;
317 }
318 }
319 B2ERROR("ExtractEvent: Histogram \"DAQ/Nevent\" missing");
320}
321
322int DQMHistAnalysisModule::registerEpicsPV(std::string pvname, std::string keyname)
323{
324 return registerEpicsPVwithPrefix(m_PVPrefix, pvname, keyname);
325}
326
327int DQMHistAnalysisModule::registerExternalEpicsPV(std::string pvname, std::string keyname)
328{
329 return registerEpicsPVwithPrefix(std::string(""), pvname, keyname);
330}
331
332int DQMHistAnalysisModule::registerEpicsPVwithPrefix(std::string prefix, std::string pvname, std::string keyname)
333{
334 if (!m_useEpics) return -1;
335#ifdef _BELLE2_EPICS
336 if (m_epicsNameToChID[pvname] != nullptr) {
337 B2ERROR("Epics PV " << pvname << " already registered!");
338 return -1;
339 }
340 if (keyname != "" && m_epicsNameToChID[keyname] != nullptr) {
341 B2ERROR("Epics PV with key " << keyname << " already registered!");
342 return -1;
343 }
344
345 m_epicsChID.emplace_back();
346 auto ptr = &m_epicsChID.back();
347 if (!ca_current_context()) SEVCHK(ca_context_create(ca_disable_preemptive_callback), "ca_context_create");
348 // the subscribed name includes the prefix, the map below does *not*
349 CheckEpicsError(ca_create_channel((prefix + pvname).data(), NULL, NULL, 10, ptr), "ca_create_channel failure", pvname);
350
351 m_epicsNameToChID[pvname] = *ptr;
352 if (keyname != "") m_epicsNameToChID[keyname] = *ptr;
353 return m_epicsChID.size() - 1; // return index to last added item
354#else
355 return -1;
356#endif
357}
358
359void DQMHistAnalysisModule::setEpicsPV(std::string keyname, double value)
360{
361 if (!m_useEpics || m_epicsReadOnly) return;
362#ifdef _BELLE2_EPICS
363 if (m_epicsNameToChID[keyname] == nullptr) {
364 B2ERROR("Epics PV " << keyname << " not registered!");
365 return;
366 }
367 CheckEpicsError(ca_put(DBR_DOUBLE, m_epicsNameToChID[keyname], (void*)&value), "ca_set failure", keyname);
368#endif
369}
370
371void DQMHistAnalysisModule::setEpicsPV(std::string keyname, int value)
372{
373 if (!m_useEpics || m_epicsReadOnly) return;
374#ifdef _BELLE2_EPICS
375 if (m_epicsNameToChID[keyname] == nullptr) {
376 B2ERROR("Epics PV " << keyname << " not registered!");
377 return;
378 }
379 CheckEpicsError(ca_put(DBR_SHORT, m_epicsNameToChID[keyname], (void*)&value), "ca_set failure", keyname);
380#endif
381}
382
383void DQMHistAnalysisModule::setEpicsStringPV(std::string keyname, std::string value)
384{
385 if (!m_useEpics || m_epicsReadOnly) return;
386#ifdef _BELLE2_EPICS
387 if (m_epicsNameToChID[keyname] == nullptr) {
388 B2ERROR("Epics PV " << keyname << " not registered!");
389 return;
390 }
391 if (value.length() > 40) {
392 B2ERROR("Epics string PV " << keyname << " too long (>40 characters)!");
393 return;
394 }
395 char text[40];
396 strcpy(text, value.c_str());
397 CheckEpicsError(ca_put(DBR_STRING, m_epicsNameToChID[keyname], text), "ca_set failure", keyname);
398#endif
399}
400
401void DQMHistAnalysisModule::setEpicsPV(int index, double value)
402{
403 if (!m_useEpics || m_epicsReadOnly) return;
404#ifdef _BELLE2_EPICS
405 if (index < 0 || index >= (int)m_epicsChID.size()) {
406 B2ERROR("Epics PV with " << index << " not registered!");
407 return;
408 }
409 CheckEpicsError(ca_put(DBR_DOUBLE, m_epicsChID[index], (void*)&value), "ca_set failure", m_epicsChID[index]);
410#endif
411}
412
413void DQMHistAnalysisModule::setEpicsPV(int index, int value)
414{
415 if (!m_useEpics || m_epicsReadOnly) return;
416#ifdef _BELLE2_EPICS
417 if (index < 0 || index >= (int)m_epicsChID.size()) {
418 B2ERROR("Epics PV with " << index << " not registered!");
419 return;
420 }
421 CheckEpicsError(ca_put(DBR_SHORT, m_epicsChID[index], (void*)&value), "ca_set failure", m_epicsChID[index]);
422#endif
423}
424
425void DQMHistAnalysisModule::setEpicsStringPV(int index, std::string value)
426{
427 if (!m_useEpics || m_epicsReadOnly) return;
428#ifdef _BELLE2_EPICS
429 if (index < 0 || index >= (int)m_epicsChID.size()) {
430 B2ERROR("Epics PV with " << index << " not registered!");
431 return;
432 }
433 char text[41];
434 strncpy(text, value.c_str(), 40);
435 text[40] = 0;
436 CheckEpicsError(ca_put(DBR_STRING, m_epicsChID[index], text), "ca_set failure", m_epicsChID[index]);
437#endif
438}
439
440double DQMHistAnalysisModule::getEpicsPV(std::string keyname)
441{
442 double value{NAN};
443 if (!m_useEpics) return value;
444#ifdef _BELLE2_EPICS
445 if (m_epicsNameToChID[keyname] == nullptr) {
446 B2ERROR("Epics PV " << keyname << " not registered!");
447 return value;
448 }
449 // From EPICS doc. When ca_get or ca_array_get are invoked the returned channel value cant be assumed to be stable
450 // in the application supplied buffer until after ECA_NORMAL is returned from ca_pend_io. If a connection is lost
451 // outstanding get requests are not automatically reissued following reconnect.
452 auto r = ca_get(DBR_DOUBLE, m_epicsNameToChID[keyname], (void*)&value);
453 if (r == ECA_NORMAL) r = ca_pend_io(5.0); // this is needed!
454 if (r == ECA_NORMAL) {
455 return value;
456 } else {
457 CheckEpicsError(r, "Read PV failed in ca_get or ca_pend_io failure", keyname);
458 }
459#endif
460 return NAN;
461}
462
464{
465 double value{NAN};
466 if (!m_useEpics) return value;
467#ifdef _BELLE2_EPICS
468 if (index < 0 || index >= (int)m_epicsChID.size()) {
469 B2ERROR("Epics PV with " << index << " not registered!");
470 return value;
471 }
472 // From EPICS doc. When ca_get or ca_array_get are invoked the returned channel value cant be assumed to be stable
473 // in the application supplied buffer until after ECA_NORMAL is returned from ca_pend_io. If a connection is lost
474 // outstanding get requests are not automatically reissued following reconnect.
475 auto r = ca_get(DBR_DOUBLE, m_epicsChID[index], (void*)&value);
476 if (r == ECA_NORMAL) r = ca_pend_io(5.0); // this is needed!
477 if (r == ECA_NORMAL) {
478 return value;
479 } else {
480 CheckEpicsError(r, "Read PV failed in ca_get or ca_pend_io failure", m_epicsChID[index]);
481 }
482#endif
483 return NAN;
484}
485
486std::string DQMHistAnalysisModule::getEpicsStringPV(std::string keyname, bool& status)
487{
488 status = false;
489 char value[40] = "";
490 if (!m_useEpics) return std::string(value);
491#ifdef _BELLE2_EPICS
492 if (m_epicsNameToChID[keyname] == nullptr) {
493 B2ERROR("Epics PV " << keyname << " not registered!");
494 return std::string(value);
495 }
496 // From EPICS doc. When ca_get or ca_array_get are invoked the returned channel value cant be assumed to be stable
497 // in the application supplied buffer until after ECA_NORMAL is returned from ca_pend_io. If a connection is lost
498 // outstanding get requests are not automatically reissued following reconnect.
499 auto r = ca_get(DBR_STRING, m_epicsNameToChID[keyname], value);
500 if (r == ECA_NORMAL) r = ca_pend_io(5.0); // this is needed!
501 if (r == ECA_NORMAL) {
502 status = true;
503 return std::string(value);
504 } else {
505 CheckEpicsError(r, "Read PV (string) failed in ca_get or ca_pend_io failure", keyname);
506 }
507#endif
508 return std::string(value);
509}
510
511std::string DQMHistAnalysisModule::getEpicsStringPV(int index, bool& status)
512{
513 status = false;
514 char value[40] = "";
515 if (!m_useEpics) return std::string(value);
516#ifdef _BELLE2_EPICS
517 if (index < 0 || index >= (int)m_epicsChID.size()) {
518 B2ERROR("Epics PV with " << index << " not registered!");
519 return std::string(value);
520 }
521 // From EPICS doc. When ca_get or ca_array_get are invoked the returned channel value cant be assumed to be stable
522 // in the application supplied buffer until after ECA_NORMAL is returned from ca_pend_io. If a connection is lost
523 // outstanding get requests are not automatically reissued following reconnect.
524 auto r = ca_get(DBR_DOUBLE, m_epicsChID[index], value);
525 if (r == ECA_NORMAL) r = ca_pend_io(5.0); // this is needed!
526 if (r == ECA_NORMAL) {
527 status = true;
528 return std::string(value);
529 } else {
530 CheckEpicsError(r, "Read PV (string) failed in ca_get or ca_pend_io failure", m_epicsChID[index]);
531 }
532#endif
533 return std::string(value);
534}
535
537{
538#ifdef _BELLE2_EPICS
539 if (m_useEpics) {
540 if (m_epicsNameToChID[keyname] != nullptr) {
541 return m_epicsNameToChID[keyname];
542 } else {
543 B2ERROR("Epics PV " << keyname << " not registered!");
544 }
545 }
546#endif
547 return nullptr;
548}
549
551{
552#ifdef _BELLE2_EPICS
553 if (m_useEpics) {
554 if (index >= 0 && index < (int)m_epicsChID.size()) {
555 return m_epicsChID[index];
556 } else {
557 B2ERROR("Epics PV with " << index << " not registered!");
558 }
559 }
560#endif
561 return nullptr;
562}
563
565{
566 int state = ECA_NORMAL;
567 if (!m_useEpics) return state;
568#ifdef _BELLE2_EPICS
569 if (wait > 0.) {
570 state = ca_pend_io(wait);
571 SEVCHK(state, "ca_pend_io failure");
572 }
573#endif
574 return state;
575}
576
578{
579 // this should be called in terminate function of analysis modules
580#ifdef _BELLE2_EPICS
581 if (getUseEpics()) {
582 for (auto& it : m_epicsChID) CheckEpicsError(ca_clear_channel(it), "ca_clear_channel failure", it);
583 updateEpicsPVs(5.0);
584 // Make sure we clean up both afterwards!
585 m_epicsChID.clear();
586 m_epicsNameToChID.clear();
587 }
588#endif
589}
590
591bool DQMHistAnalysisModule::requestLimitsFromEpicsPVs(std::string name, double& lowerAlarm, double& lowerWarn, double& upperWarn,
592 double& upperAlarm)
593{
594 return requestLimitsFromEpicsPVs(getEpicsPVChID(name), lowerAlarm, lowerWarn, upperWarn, upperAlarm);
595}
596
597bool DQMHistAnalysisModule::requestLimitsFromEpicsPVs(int index, double& lowerAlarm, double& lowerWarn, double& upperWarn,
598 double& upperAlarm)
599{
600 return requestLimitsFromEpicsPVs(getEpicsPVChID(index), lowerAlarm, lowerWarn, upperWarn, upperAlarm);
601}
602
603bool DQMHistAnalysisModule::requestLimitsFromEpicsPVs(chid pv, double& lowerAlarm, double& lowerWarn, double& upperWarn,
604 double& upperAlarm)
605{
606 // get warn and error limit only if pv exists
607 // overwrite only if limit is defined (not NaN)
608 // user should initilize with NaN before calling, unless
609 // some "default" values should be set otherwise
610 if (pv != nullptr) {
611 struct dbr_ctrl_double tPvData;
612 // From EPICS doc. When ca_get or ca_array_get are invoked the returned channel value cant be assumed to be stable
613 // in the application supplied buffer until after ECA_NORMAL is returned from ca_pend_io. If a connection is lost
614 // outstanding get requests are not automatically reissued following reconnect.
615 auto r = ca_get(DBR_CTRL_DOUBLE, pv, &tPvData);
616 if (r == ECA_NORMAL) r = ca_pend_io(5.0); // this is needed!
617 if (r == ECA_NORMAL) {
618 if (!std::isnan(tPvData.lower_alarm_limit)) {
619 lowerAlarm = tPvData.lower_alarm_limit;
620 }
621 if (!std::isnan(tPvData.lower_warning_limit)) {
622 lowerWarn = tPvData.lower_warning_limit;
623 }
624 if (!std::isnan(tPvData.upper_warning_limit)) {
625 upperWarn = tPvData.upper_warning_limit;
626 }
627 if (!std::isnan(tPvData.upper_alarm_limit)) {
628 upperAlarm = tPvData.upper_alarm_limit;
629 }
630 return true;
631 } else {
632 CheckEpicsError(r, "Reading PV Limits failed in ca_get or ca_pend_io failure", pv);
633 }
634 }
635 return false;
636}
637
638DQMHistAnalysisModule::EStatus DQMHistAnalysisModule::makeStatus(bool enough, bool warn_flag, bool error_flag)
639{
640 // white color is the default, if no colorize
641 if (!enough) {
642 return (c_StatusTooFew);
643 } else {
644 if (error_flag) {
645 return (c_StatusError);
646 } else if (warn_flag) {
647 return (c_StatusWarning);
648 } else {
649 return (c_StatusGood);
650 }
651 }
652
653 return (c_StatusDefault); // default, but should not be reached
654}
655
657{
658 // white color is the default, if no colorize
660 switch (stat) {
661 case c_StatusTooFew:
662 color = c_ColorTooFew; // Magenta or Gray
663 break;
664 case c_StatusDefault:
665 color = c_ColorDefault; // default no colors
666 break;
667 case c_StatusGood:
668 color = c_ColorGood; // Good
669 break;
670 case c_StatusWarning:
671 color = c_ColorWarning; // Warning
672 break;
673 case c_StatusError:
674 color = c_ColorError; // Severe
675 break;
676 default:
677 color = c_ColorDefault; // default no colors
678 break;
679 }
680 return color;
681}
682
684{
685 if (!canvas) return;
686 auto color = getStatusColor(stat);
687
688 canvas->Pad()->SetFillColor(color);
689
690 canvas->Pad()->SetFrameFillColor(10); // White (kWhite is not used since it results in transparent!)
691 canvas->Pad()->SetFrameFillStyle(1001);// White
692 canvas->Pad()->Modified();
693 canvas->Pad()->Update();
694}
695
697{
698 B2INFO("Check PV Connections");
699
700 for (auto& it : m_epicsChID) {
701 printPVStatus(it);
702 }
703 B2INFO("Check PVs done");
704}
705
706void DQMHistAnalysisModule::printPVStatus(chid pv, bool onlyError)
707{
708 if (pv == nullptr) {
709 B2WARNING("PV chid was nullptr");
710 return;
711 }
712 auto state = ca_state(pv);
713 switch (state) {
714 case cs_never_conn: /* valid chid, server not found or unavailable */
715 B2WARNING("Channel never connected " << ca_name(pv));
716 break;
717 case cs_prev_conn: /* valid chid, previously connected to server */
718 B2WARNING("Channel was connected, but now is not " << ca_name(pv));
719 break;
720 case cs_closed: /* channel deleted by user */
721 B2WARNING("Channel deleted already " << ca_name(pv));
722 break;
723 case cs_conn: /* valid chid, connected to server */
724 if (!onlyError) B2INFO("Channel connected and OK " << ca_name(pv));
725 break;
726 default:
727 B2WARNING("Undefined status for channel " << ca_name(pv));
728 break;
729 }
730}
731
732void DQMHistAnalysisModule::CheckEpicsError(int state, const std::string& message, const std::string& name)
733{
734 if (state != ECA_NORMAL) {
735 B2WARNING(message << ": " << name);
736 printPVStatus(m_epicsNameToChID[name], false);
737 }
738}
739
740void DQMHistAnalysisModule::CheckEpicsError(int state, const std::string& message, chid id = nullptr)
741{
742 if (state != ECA_NORMAL) {
743 std::string name;
744 if (id) name = ca_name(id);
745 B2WARNING(message << ": " << name);
746 printPVStatus(id, false);
747 }
748}
749
static MonObjList s_monObjList
The list of MonitoringObjects.
TCanvas * findCanvas(TString cname)
Find canvas by name.
void printPVStatus(chid pv, bool onlyError=true)
check the status of a PVs and report if disconnected or not found
bool hasDeltaPar(const std::string &dirname, const std::string &histname)
Check if Delta histogram parameters exist for histogram.
std::map< std::string, HistObject > HistList
The type of list of histograms.
static MonitoringObject * getMonitoringObject(const std::string &name)
Get MonitoringObject with given name (new object is created if non-existing)
std::map< std::string, MonitoringObject > MonObjList
The type of list of MonitoringObjects.
void addDeltaPar(const std::string &dirname, const std::string &histname, HistDelta::EDeltaType t, int p, unsigned int a=1)
Add Delta histogram parameters.
static TH1 * findHistInFile(TFile *file, const std::string &histname)
Find histogram in specific TFile (e.g.
EStatusColor getStatusColor(EStatus status)
Return color for canvas state.
void colorizeCanvas(TCanvas *canvas, EStatus status)
Helper function for Canvas colorization.
static TH1 * findHist(const std::string &histname, bool onlyIfUpdated=false)
Get histogram from list (no other search).
static MonitoringObject * findMonitoringObject(const std::string &objName)
Find MonitoringObject.
void clearlist(void)
Clear all static global lists.
double getSigma68(TH1 *h) const
Helper function to compute half of the central interval covering 68% of a distribution.
EStatusColor
Status colors of histogram/canvas (corresponding to status)
@ 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
double getEpicsPV(std::string keyname)
Read value from a EPICS PV.
static int s_eventProcessed
Number of Events processed to fill histograms.
std::map< std::string, bool > CanvasUpdatedList
The type of list of canvas updated status.
std::string getEpicsStringPV(std::string keyname, bool &status)
Read value from a EPICS PV.
int registerExternalEpicsPV(std::string pvname, std::string keyname="")
Register a PV with its name and a key name.
static HistList s_histList
The list of Histograms.
static std::string s_runType
The Run type.
static void clearHistList(void)
Clears the list of histograms.
TH1 * getDelta(const std::string &fullname, int n=0, bool onlyIfUpdated=true)
Get Delta histogram.
std::vector< std::string > StringSplit(const std::string &s, const char delim)
Helper function for string token split.
std::map< std::string, HistDelta > DeltaList
The type of list of delta settings and histograms.
void setEpicsPV(std::string keyname, double value)
Write value to a EPICS PV.
static DeltaList s_deltaList
The list of Delta Histograms and settings.
DQMHistAnalysisModule()
Constructor / Destructor.
void checkPVStatus(void)
Check the status of all PVs and report if disconnected or not found.
static bool m_epicsReadOnly
Flag if to use EPICS in ReadOnly mode (for reading limits) do not set by yourself,...
EStatus
Status flag of histogram/canvas.
@ c_StatusDefault
default for non-coloring
@ c_StatusTooFew
Not enough entries/event to judge.
@ c_StatusError
Analysis result: Severe issue found.
@ c_StatusWarning
Analysis result: Warning, there may be minor issues.
@ c_StatusGood
Analysis result: Good.
static bool addHist(const std::string &dirname, const std::string &histname, TH1 *h)
Add histogram.
bool getUseEpics(void)
Getter for EPICS usage.
void ExtractRunType(std::vector< TH1 * > &hs)
Extract Run Type from histogram title, called from input module.
void CheckEpicsError(int state, const std::string &message, const std::string &name)
check the return status and check PV in case of error
TH1 * findHistInCanvas(const std::string &hname, TCanvas **canvas=nullptr)
Find histogram in corresponding canvas.
static std::string m_PVPrefix
The Prefix for EPICS PVs.
void cleanupEpicsPVs(void)
Unsubscribe from EPICS PVs on terminate.
void clearCanvases(void)
Clear content of all Canvases.
EStatus makeStatus(bool enough, bool warn_flag, bool error_flag)
Helper function to judge the status for coloring and EPICS.
static bool m_useEpics
Flag if to use EPICS do not set by yourself, use EpicsEnable module to set.
static void initHistListBeforeEvent(void)
Reset the list of histograms.
void ExtractEvent(std::vector< TH1 * > &hs)
Extract event processed from daq histogram, called from input module.
int registerEpicsPV(std::string pvname, std::string keyname="")
EPICS related Functions.
void UpdateCanvas(std::string name, bool updated=true)
Mark canvas as updated (or not)
void resetDeltaList(void)
Reset Delta.
chid getEpicsPVChID(std::string keyname)
Get EPICS PV Channel Id.
bool requestLimitsFromEpicsPVs(chid id, double &lowerAlarm, double &lowerWarn, double &upperWarn, double &upperAlarm)
Get Alarm Limits from EPICS PV.
int registerEpicsPVwithPrefix(std::string prefix, std::string pvname, std::string keyname="")
Register a PV with its name and a key name.
void setEpicsStringPV(std::string keyname, std::string value)
Write string to a EPICS PV.
int updateEpicsPVs(float timeout)
Update all EPICS PV (flush to network)
static CanvasUpdatedList s_canvasUpdatedList
The list of canvas updated status.
EDeltaType
enum definition for delta algo Disabled: nothing Entries: use nr histogram entries Underflow: use ent...
Definition: HistDelta.h:32
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
MonitoringObject is a basic object to hold data for the run-dependency monitoring Run summary TCanvas...
#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.
STL namespace.