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