13#include <dqm/core/DQMHistAnalysis.h>
14#include <boost/algorithm/string.hpp>
36std::vector <chid> DQMHistAnalysisModule::m_epicsChID;
62 if (dirname.size() > 0) {
63 fullname = dirname +
"/" + histname;
72 B2DEBUG(20,
"Found Delta" << fullname);
83 string histname = hist->GetName();
84 std::string name = dirname +
"/" + histname;
86 n.m_orghist_name = name;
87 n.m_refhist_name =
"ref/" + name;
88 hist->SetName((n.m_refhist_name).c_str());
89 hist->SetDirectory(0);
91 n.setRefCopy(
nullptr);
99 if (dirname.size() > 0) {
100 fullname = dirname +
"/" + histname;
109 std::string fullname;
110 if (dirname.size() > 0) {
111 fullname = dirname +
"/" + histname;
120 std::string fullname = dirname +
"/" + histname;
121 if (dirname.size() == 0) fullname = histname;
122 if (histname.size() == 0) fullname = dirname;
126 return it->second.getDelta(n, onlyIfUpdated);
128 B2WARNING(
"Delta hist " << fullname <<
" not found");
135 obj->SetName(objName.c_str());
141 TIter nextkey(gROOT->GetListOfCanvases());
144 while ((obj =
dynamic_cast<TObject*
>(nextkey()))) {
145 if (obj->IsA()->InheritsFrom(
"TCanvas")) {
146 if (obj->GetName() == canvas_name)
147 return dynamic_cast<TCanvas*
>(obj);
156 std::string fullname = dirname +
"/" + histname;
157 if (dirname.size() == 0) fullname = histname;
158 if (histname.size() == 0) fullname = dirname;
161 if (was_updated && !
s_histList[fullname].isUpdated())
return nullptr;
165 B2ERROR(
"Histogram " << fullname <<
" in histogram list but nullptr.");
168 B2INFO(
"Histogram " << fullname <<
" not in list.");
184 if (hist->Integral() != 0 and ref->Integral() != 0) {
185 ref->Scale(hist->Integral() / ref->Integral());
190 if (hist->GetMaximum() != 0 and ref->GetMaximum() != 0) {
191 ref->Scale(hist->GetMaximum() / ref->GetMaximum());
201 std::string fullname = dirname +
"/" + histname;
202 if (dirname.size() == 0) fullname = histname;
203 if (histname.size() == 0) fullname = dirname;
216 TCanvas* cnv =
nullptr;
218 if (cobj) cnv = *cobj;
220 if (cnv ==
nullptr) {
224 B2ERROR(
"findHistInCanvas: histoname not valid (missing dir?), should be 'dirname/histname': " << histo_name);
227 auto dirname = s.at(0);
228 auto hname = s.at(1);
229 std::string canvas_name = dirname +
"/c_" + hname;
232 if (cnv && cobj) *cobj = cnv;
236 if (cnv !=
nullptr) {
237 TIter nextkey(cnv->GetListOfPrimitives());
239 while ((obj =
dynamic_cast<TObject*
>(nextkey()))) {
240 if (obj->IsA()->InheritsFrom(
"TH1")) {
241 if (obj->GetName() == histo_name)
242 return dynamic_cast<TH1*
>(obj);
253 if (file && file->IsOpen()) {
254 auto obj = file->Get(histname.data());
255 if (obj !=
nullptr) {
257 if (obj->IsA()->InheritsFrom(
"TH1")) {
258 B2DEBUG(20,
"Histogram " << histname <<
" found in file");
259 return dynamic_cast<TH1*
>(obj);
261 B2INFO(
"Found Object " << histname <<
" in file is not a histogram");
264 B2INFO(
"Histogram " << histname <<
" not found in file");
275 B2INFO(
"MonitoringObject " << objName <<
" not in memfile.");
281 double probs[2] = {0.16, 1 - 0.16};
282 double quant[2] = {0, 0};
283 h->GetQuantiles(2, quant, probs);
284 const double sigma68 = (-quant[0] + quant[1]) / 2;
290 std::vector <std::string> out;
291 boost::split(out, in, [delim](
char c) {
return c == delim;});
297 TIter nextckey(gROOT->GetListOfCanvases());
298 TObject* cobj =
nullptr;
300 while ((cobj =
dynamic_cast<TObject*
>(nextckey()))) {
301 if (cobj->IsA()->InheritsFrom(
"TCanvas")) {
302 TCanvas* cnv =
dynamic_cast<TCanvas*
>(cobj);
313 it.second.resetBeforeEvent();
317 it.second.setNotUpdated();
353 for (
size_t i = 0; i < hs.size(); i++) {
354 if (hs[i]->GetName() == std::string(
"DQMInfo/rtype")) {
359 B2ERROR(
"ExtractRunType: Histogram \"DQMInfo/rtype\" missing");
365 for (
size_t i = 0; i < hs.size(); i++) {
366 if (hs[i]->GetName() == std::string(
"DAQ/Nevent")) {
371 B2ERROR(
"ExtractEvent: Histogram \"DAQ/Nevent\" missing");
385 const std::string& keyname)
389 if (m_epicsNameToChID[pvname] !=
nullptr) {
390 B2ERROR(
"Epics PV " << pvname <<
" already registered!");
393 if (keyname !=
"" && m_epicsNameToChID[keyname] !=
nullptr) {
394 B2ERROR(
"Epics PV with key " << keyname <<
" already registered!");
398 m_epicsChID.emplace_back();
399 auto ptr = &m_epicsChID.back();
400 if (!ca_current_context()) SEVCHK(ca_context_create(ca_disable_preemptive_callback),
"ca_context_create");
402 CheckEpicsError(ca_create_channel((prefix + pvname).data(), NULL, NULL, 10, ptr),
"ca_create_channel failure", pvname);
404 m_epicsNameToChID[pvname] = *ptr;
405 if (keyname !=
"") m_epicsNameToChID[keyname] = *ptr;
406 return m_epicsChID.size() - 1;
416 if (m_epicsNameToChID[keyname] ==
nullptr) {
417 B2ERROR(
"Epics PV " << keyname <<
" not registered!");
420 CheckEpicsError(ca_put(DBR_DOUBLE, m_epicsNameToChID[keyname], (
void*)&value),
"ca_set failure", keyname);
428 if (m_epicsNameToChID[keyname] ==
nullptr) {
429 B2ERROR(
"Epics PV " << keyname <<
" not registered!");
432 CheckEpicsError(ca_put(DBR_SHORT, m_epicsNameToChID[keyname], (
void*)&value),
"ca_set failure", keyname);
440 if (m_epicsNameToChID[keyname] ==
nullptr) {
441 B2ERROR(
"Epics PV " << keyname <<
" not registered!");
444 if (value.length() > 40) {
445 B2ERROR(
"Epics string PV " << keyname <<
" too long (>40 characters)!");
449 strcpy(text, value.c_str());
450 CheckEpicsError(ca_put(DBR_STRING, m_epicsNameToChID[keyname], text),
"ca_set failure", keyname);
458 if (index < 0 || index >= (
int)m_epicsChID.size()) {
459 B2ERROR(
"Epics PV with " << index <<
" not registered!");
462 CheckEpicsError(ca_put(DBR_DOUBLE, m_epicsChID[index], (
void*)&value),
"ca_set failure", m_epicsChID[index]);
470 if (index < 0 || index >= (
int)m_epicsChID.size()) {
471 B2ERROR(
"Epics PV with " << index <<
" not registered!");
474 CheckEpicsError(ca_put(DBR_SHORT, m_epicsChID[index], (
void*)&value),
"ca_set failure", m_epicsChID[index]);
482 if (index < 0 || index >= (
int)m_epicsChID.size()) {
483 B2ERROR(
"Epics PV with " << index <<
" not registered!");
487 strncpy(text, value.c_str(), 40);
489 CheckEpicsError(ca_put(DBR_STRING, m_epicsChID[index], text),
"ca_set failure", m_epicsChID[index]);
498 if (m_epicsNameToChID[keyname] ==
nullptr) {
499 B2ERROR(
"Epics PV " << keyname <<
" not registered!");
505 auto r = ca_get(DBR_DOUBLE, m_epicsNameToChID[keyname], (
void*)&value);
506 if (r == ECA_NORMAL) r = ca_pend_io(5.0);
507 if (r == ECA_NORMAL) {
510 CheckEpicsError(r,
"Read PV failed in ca_get or ca_pend_io failure", keyname);
521 if (index < 0 || index >= (
int)m_epicsChID.size()) {
522 B2ERROR(
"Epics PV with " << index <<
" not registered!");
528 auto r = ca_get(DBR_DOUBLE, m_epicsChID[index], (
void*)&value);
529 if (r == ECA_NORMAL) r = ca_pend_io(5.0);
530 if (r == ECA_NORMAL) {
533 CheckEpicsError(r,
"Read PV failed in ca_get or ca_pend_io failure", m_epicsChID[index]);
545 if (m_epicsNameToChID[keyname] ==
nullptr) {
546 B2ERROR(
"Epics PV " << keyname <<
" not registered!");
547 return std::string(value);
552 auto r = ca_get(DBR_STRING, m_epicsNameToChID[keyname], value);
553 if (r == ECA_NORMAL) r = ca_pend_io(5.0);
554 if (r == ECA_NORMAL) {
556 return std::string(value);
558 CheckEpicsError(r,
"Read PV (string) failed in ca_get or ca_pend_io failure", keyname);
561 return std::string(value);
570 if (index < 0 || index >= (
int)m_epicsChID.size()) {
571 B2ERROR(
"Epics PV with " << index <<
" not registered!");
572 return std::string(value);
577 auto r = ca_get(DBR_STRING, m_epicsChID[index], value);
578 if (r == ECA_NORMAL) r = ca_pend_io(5.0);
579 if (r == ECA_NORMAL) {
581 return std::string(value);
583 CheckEpicsError(r,
"Read PV (string) failed in ca_get or ca_pend_io failure", m_epicsChID[index]);
586 return std::string(value);
593 if (m_epicsNameToChID[keyname] !=
nullptr) {
594 return m_epicsNameToChID[keyname];
596 B2ERROR(
"Epics PV " << keyname <<
" not registered!");
607 if (index >= 0 && index < (
int)m_epicsChID.size()) {
608 return m_epicsChID[index];
610 B2ERROR(
"Epics PV with " << index <<
" not registered!");
619 int state = ECA_NORMAL;
623 state = ca_pend_io(wait);
624 SEVCHK(state,
"ca_pend_io failure");
635 for (
auto& it : m_epicsChID)
CheckEpicsError(ca_clear_channel(it),
"ca_clear_channel failure", it);
639 m_epicsNameToChID.clear();
645 double& upperWarn,
double& upperAlarm)
664 struct dbr_ctrl_double tPvData;
668 auto r = ca_get(DBR_CTRL_DOUBLE, pv, &tPvData);
669 if (r == ECA_NORMAL) r = ca_pend_io(5.0);
670 if (r == ECA_NORMAL) {
671 if (!std::isnan(tPvData.lower_alarm_limit)) {
672 lowerAlarm = tPvData.lower_alarm_limit;
674 if (!std::isnan(tPvData.lower_warning_limit)) {
675 lowerWarn = tPvData.lower_warning_limit;
677 if (!std::isnan(tPvData.upper_warning_limit)) {
678 upperWarn = tPvData.upper_warning_limit;
680 if (!std::isnan(tPvData.upper_alarm_limit)) {
681 upperAlarm = tPvData.upper_alarm_limit;
685 CheckEpicsError(r,
"Reading PV Limits failed in ca_get or ca_pend_io failure", pv);
699 }
else if (warn_flag) {
741 canvas->Pad()->SetFillColor(color);
743 canvas->Pad()->SetFrameFillColor(10);
744 canvas->Pad()->SetFrameFillStyle(1001);
745 canvas->Pad()->Modified();
746 canvas->Pad()->Update();
751 B2INFO(
"Check PV Connections");
753 for (
const auto& it : m_epicsChID) {
756 B2INFO(
"Check PVs done");
762 B2WARNING(
"PV chid was nullptr");
765 auto state = ca_state(pv);
768 B2WARNING(
"Channel never connected " << ca_name(pv));
771 B2WARNING(
"Channel was connected, but now is not " << ca_name(pv));
774 B2WARNING(
"Channel deleted already " << ca_name(pv));
777 if (!onlyError) B2INFO(
"Channel connected and OK " << ca_name(pv));
780 B2WARNING(
"Undefined status for channel " << ca_name(pv));
787 if (state != ECA_NORMAL) {
788 B2WARNING(message <<
": " << name);
795 if (state != ECA_NORMAL) {
797 if (
id) name = ca_name(
id);
798 B2WARNING(message <<
": " << name);
static MonObjList s_monObjList
The list of MonitoringObjects.
static TCanvas * findCanvas(TString cname)
Find canvas by name.
static void printPVStatus(chid pv, bool onlyError=true)
check the status of a PVs and report if disconnected or not found
static bool hasDeltaPar(const std::string &dirname, const std::string &histname)
Check if Delta histogram parameters exist for histogram.
chid getEpicsPVChID(const std::string &keyname)
Get EPICS PV Channel Id.
static bool getUseEpics(void)
Getter for EPICS usage.
std::map< std::string, HistObject > HistList
The type of list of histograms.
int registerEpicsPV(const std::string &pvname, const std::string &keyname="")
EPICS related Functions.
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.
static TH1 * scaleReference(ERefScaling scaling, const TH1 *hist, TH1 *ref)
Using the original and reference, create scaled version.
int registerExternalEpicsPV(const std::string &pvname, const std::string &keyname="")
Register a PV with its name and a key name.
static void addDeltaPar(const std::string &dirname, const std::string &histname, HistDelta::EDeltaType t, int p, unsigned int a=1)
Add Delta histogram parameters.
static double getSigma68(TH1 *h)
Helper function to compute half of the central interval covering 68% of a distribution.
static void addRefHist(const std::string &dirname, TH1 *hist)
Add reference histogram.
static TH1 * findHistInFile(TFile *file, const std::string &histname)
Find histogram in specific TFile (e.g.
static EStatusColor getStatusColor(EStatus status)
Return color for canvas state.
static void colorizeCanvas(TCanvas *canvas, EStatus status)
Helper function for Canvas colorization.
static MonitoringObject * findMonitoringObject(const std::string &objName)
Find MonitoringObject.
static void clearlist(void)
Clear all static global lists.
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
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.
static void UpdateCanvas(const std::string &name, bool updated=true)
Mark canvas as updated (or not)
static HistList s_histList
The list of Histograms.
static RefList s_refList
The list of references.
static void ExtractNEvent(std::vector< TH1 * > &hs)
Extract event processed from daq histogram, called from input module.
static std::string s_runType
The Run type.
static void clearHistList(void)
Clears the list of histograms.
static std::vector< std::string > StringSplit(const std::string &s, const char delim)
Helper function for string token split.
static void clearRefList(void)
Clears the list of ref histograms.
std::map< std::string, HistDelta > DeltaList
The type of list of delta settings and histograms.
void setEpicsStringPV(const std::string &keyname, const std::string &value)
Write string to a EPICS PV.
static DeltaList s_deltaList
The list of Delta Histograms and settings.
DQMHistAnalysisModule()
Constructor / Destructor.
static void checkPVStatus(void)
Check the status of all PVs and report if disconnected or not found.
std::map< std::string, RefHistObject > RefList
The type of list of references.
static bool m_epicsReadOnly
Flag if to use EPICS in ReadOnly mode (for reading limits) do not set by yourself,...
std::string getEpicsStringPV(const std::string &keyname, bool &status)
Read value from a EPICS PV.
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.
static 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.
TH1 * getDelta(const std::string &dirname, const std::string &histname="", int n=0, bool onlyIfUpdated=true)
Get Delta histogram.
void cleanupEpicsPVs(void)
Unsubscribe from EPICS PVs on terminate.
static void clearCanvases(void)
Clear content of all Canvases.
ERefScaling
Reference plot scaling type.
@ c_RefScaleEntries
to number of entries (integral)
@ c_RefScaleMax
to maximum (bin entry)
@ c_RefScaleNone
no scaling
static 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.
int registerEpicsPVwithPrefix(const std::string &prefix, const std::string &pvname, const std::string &keyname="")
Register a PV with its name and a key name.
double getEpicsPV(const std::string &keyname)
Read value from a EPICS PV.
static TH1 * findRefHist(const std::string &dirname, const std::string &histname="", ERefScaling scaling=ERefScaling::c_RefScaleNone, const TH1 *hist=nullptr)
Find reference histogram.
static void resetDeltaList(void)
Reset Delta.
bool requestLimitsFromEpicsPVs(chid id, double &lowerAlarm, double &lowerWarn, double &upperWarn, double &upperAlarm)
Get Alarm Limits from EPICS PV.
void setEpicsPV(const std::string &keyname, double value)
Write value to a EPICS PV.
static TH1 * findHist(const std::string &dirname, const std::string &histname="", bool onlyIfUpdated=false)
Find histogram.
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...
void setDescription(const std::string &description)
Sets the description of the module.
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.
Abstract base class for different kinds of events.